From f958ab7af933ffefac7991e05e80ed51a06d11fd Mon Sep 17 00:00:00 2001 From: louis <869322496@qq.com> Date: Wed, 17 Apr 2024 09:59:18 +0800 Subject: [PATCH] feat: develop domain --- src/modules/domian/domain.controller.ts | 2 - .../in_out/materials_in_out.controller.ts | 25 +++- .../in_out/materials_in_out.dto.ts | 44 +++++- .../in_out/materials_in_out.service.ts | 128 +++++++++++++++++- .../materials_inventory.controller.ts | 4 +- .../materials_inventory.dto.ts | 9 +- .../materials_inventory.service.ts | 118 +++++++++------- src/modules/project/project.controller.ts | 9 +- src/modules/project/project.dto.ts | 6 +- src/modules/project/project.entity.ts | 5 + src/modules/user/dto/user.dto.ts | 7 +- src/modules/user/user.controller.ts | 8 +- src/shared/database/field-search/index.ts | 4 +- 13 files changed, 286 insertions(+), 83 deletions(-) diff --git a/src/modules/domian/domain.controller.ts b/src/modules/domian/domain.controller.ts index e0ca43b..0bd02a3 100644 --- a/src/modules/domian/domain.controller.ts +++ b/src/modules/domian/domain.controller.ts @@ -17,7 +17,6 @@ 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', @@ -33,7 +32,6 @@ export class DomainController { @Get() @ApiOperation({ summary: '获取域列表' }) @ApiResult({ type: [DomainEntity], isPage: true }) - @Perm(permissions.LIST) async list(@Query() dto: DomainQueryDto) { return this.domainService.findAll(dto); } 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 842e065..c41a04d 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 @@ -1,4 +1,4 @@ -import { Body, Controller, Delete, Get, Post, Put, Query } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Post, Put, Query, Res } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { ApiResult } from '~/common/decorators/api-result.decorator'; import { IdParam } from '~/common/decorators/id-param.decorator'; @@ -9,23 +9,38 @@ import { definePermission, Perm } from '~/modules/auth/decorators/permission.dec import { MaterialsInOutQueryDto, MaterialsInOutDto, - MaterialsInOutUpdateDto + MaterialsInOutUpdateDto, + MaterialsInOutExportDto } from './materials_in_out.dto'; import { Domain, DomainType, SkDomain } from '~/common/decorators/domain.decorator'; - +import { FastifyReply } from 'fastify'; export const permissions = definePermission('materials_inventory:history_in_out', { LIST: 'list', CREATE: 'create', READ: 'read', UPDATE: 'update', - DELETE: 'delete' + DELETE: 'delete', + EXPORT: 'export' } as const); @ApiTags('Materials In Out History - 原材料出入库记录') @ApiSecurityAuth() @Controller('materials-in-out') export class MaterialsInOutController { - constructor(private materialsInOutService: MaterialsInOutService) {} + constructor(private materialsInOutService: MaterialsInOutService) { } + + @Get('export') + @ApiOperation({ summary: '导出原材料盘点表' }) + @Perm(permissions.EXPORT) + async exportMaterialsInventoryCheck( + @Domain() domain: SkDomain, + @Query() dto: MaterialsInOutExportDto, + @Res() res: FastifyReply + ): Promise { + await this.materialsInOutService.exportMaterialsInventoryCheck({ ...dto, domain }, res); + } + + @Get() @ApiOperation({ summary: '获取原材料出入库记录列表' }) @ApiResult({ type: [MaterialsInOutEntity], isPage: true }) 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 517c41e..f4faab5 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 @@ -112,9 +112,9 @@ export class MaterialsInOutQueryDto extends IntersectionType( // 开始和结束时间用的是一天的开始和一天的结束的时分秒 return params.value ? [ - params.value[0] ? `${formatToDate(params.value[0], 'YYYY-MM-DD')} 00:00:00` : null, - params.value[1] ? `${formatToDate(params.value[1], 'YYYY-MM-DD')} 23:59:59` : null - ] + params.value[0] ? `${formatToDate(params.value[0], 'YYYY-MM-DD')} 00:00:00` : null, + params.value[1] ? `${formatToDate(params.value[1], 'YYYY-MM-DD')} 23:59:59` : null + ] : []; }) time?: string[]; @@ -159,3 +159,41 @@ export class MaterialsInOutQueryDto extends IntersectionType( @ApiProperty({ description: '是否是用于创建出库记录' }) isCreateOut?: boolean; } +export class MaterialsInOutExportDto extends IntersectionType( + + DomainType +) { + + @ApiProperty({ description: '导出时间YYYY-MM-DD' }) + @IsOptional() + @IsArray() + @Transform(params => { + // 开始和结束时间用的是一月的开始和一月的结束的时分秒 + const date = params.value; + return [ + date ? `${date[0]} 00:00:00` : null, + date ? `${date[1]} 23:59:59` : null + ]; + }) + time?: string[]; + + @ApiProperty({ description: '导出文件名' }) + @IsOptional() + @IsString() + filename?: string + + @ApiProperty({ description: '入库或出库 0:入库 1:出库' }) + @IsOptional() + @IsEnum(MaterialsInOrOutEnum) + inOrOut?: MaterialsInOrOutEnum; + + @ApiProperty({ description: '产品名称' }) + @IsOptional() + @IsString() + product?: string; + + @ApiProperty({ description: '经办人' }) + @IsOptional() + @IsString() + agent?: string; +} \ No newline at end of file diff --git a/src/modules/materials_inventory/in_out/materials_in_out.service.ts b/src/modules/materials_inventory/in_out/materials_in_out.service.ts index 3b3c318..5cc4ef6 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.service.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, In, Repository } from 'typeorm'; +import { Between, EntityManager, In, Repository } from 'typeorm'; import { Pagination } from '~/helper/paginate/pagination'; import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; @@ -10,7 +10,8 @@ import { Storage } from '~/modules/tools/storage/storage.entity'; import { MaterialsInOutQueryDto, MaterialsInOutDto, - MaterialsInOutUpdateDto + MaterialsInOutUpdateDto, + MaterialsInOutExportDto } from './materials_in_out.dto'; import { MaterialsInOutEntity } from './materials_in_out.entity'; import { fieldSearch } from '~/shared/database/field-search'; @@ -19,7 +20,9 @@ import { MaterialsInOrOutEnum, ParamConfigEnum } from '~/constants/enum'; import { MaterialsInventoryEntity } from '../materials_inventory.entity'; import { MaterialsInventoryService } from '../materials_inventory.service'; import { isDefined } from 'class-validator'; - +import { FastifyReply } from 'fastify'; +import * as ExcelJS from 'exceljs'; +import dayjs from 'dayjs'; @Injectable() export class MaterialsInOutService { constructor( @@ -31,7 +34,119 @@ export class MaterialsInOutService { @InjectRepository(ParamConfigEntity) private paramConfigRepository: Repository, private materialsInventoryService: MaterialsInventoryService - ) {} + ) { } + + + /** + * 导出出入库记录表 + */ + async exportMaterialsInventoryCheck( + { time, domain, filename, ...ext }: MaterialsInOutExportDto, + res: FastifyReply + ): Promise { + const ROW_HEIGHT = 20; + const HEADER_FONT_SIZE = 18; + + // 生成数据 + const sqb = this.buildSearchQuery() + .where(fieldSearch(ext)) + .andWhere({ + time: Between(time[0], time[1]) + }) + .andWhere('materialsInOut.isDelete = 0'); + const data = await sqb.addOrderBy('materialsInOut.time', 'DESC').getMany(); + const workbook = new ExcelJS.Workbook(); + const sheet = workbook.addWorksheet('出入库记录'); + sheet.mergeCells('A1:T1'); + // 设置标题 + sheet.getCell('A1').value = '山东矿机华信智能科技有限公司出入库记录表'; + // 设置日期 + sheet.mergeCells('A2:C2'); + sheet.getCell('A2').value = `日期:${dayjs(time[0]).format('YYYY年M月D日')}-${dayjs(time[1]).format('YYYY年M月D日')}`; + // 设置表头 + const headers = [ + '出入库单号', + '出入库', + '项目', + '公司名称', + '产品名称', + '规格型号', + '时间', + '单位', + '数量', + '单价', + '金额', + '经办人', + '领料单号', + '备注' + ]; + sheet.addRow(headers); + for (let index = 0; index < data.length; index++) { + const record = data[index]; + sheet.addRow([ + `${record.inventoryInOutNumber}`, + record.project?.name || '', + record.inOrOut === MaterialsInOrOutEnum.In ? '入库' : "出库", + record.product?.company?.name || '', + record.product?.name || '', + record.product?.productSpecification || '', + `${dayjs(record.time).format('YYYY-MM-DD HH:mm')}`, + record.product.unit.label || '', + record.quantity, + parseFloat(`${record.unitPrice || 0}`), + parseFloat(`${record.amount || 0}`), + `${record?.agent || ''}`, + record?.issuanceNumber || '', + record?.remark || '' + ]); + } + // 固定信息样式设定 + sheet.eachRow((row, index) => { + if (index >= 3) { + row.alignment = { vertical: 'middle', horizontal: 'center' }; + row.height = ROW_HEIGHT; + row.eachCell(cell => { + cell.border = { + top: { style: 'thin' }, + left: { style: 'thin' }, + bottom: { style: 'thin' }, + right: { style: 'thin' } + }; + }); + } + }); + + sheet.columns.forEach((column, index: number) => { + let maxColumnLength = 0; + const autoWidth = ['B', 'C', 'S', 'U']; + if (String.fromCharCode(65 + index) === 'B') maxColumnLength = 20; + if (autoWidth.includes(String.fromCharCode(65 + index))) { + column.eachCell({ includeEmpty: true }, (cell, rowIndex) => { + if (rowIndex >= 5) { + const columnLength = `${cell.value || ''}`.length; + if (columnLength > maxColumnLength) { + maxColumnLength = columnLength; + } + } + }); + column.width = maxColumnLength < 12 ? 12 : maxColumnLength; // Minimum width of 10 + } else { + column.width = 12; + } + }); + //读取buffer进行传输 + const buffer = await workbook.xlsx.writeBuffer(); + res + .header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + .header( + 'Content-Disposition', + `attachment; filename="${filename}.xls"` + ) + .send(buffer); + } + + + /** * 查询所有出入库记录 */ @@ -104,7 +219,8 @@ export class MaterialsInOutService { position, unitPrice, quantity, - productId + productId, + domain } = dto; inventoryInOutNumber = await this.generateInventoryInOutNumber(inOrOut); let newRecordId; @@ -115,7 +231,7 @@ export class MaterialsInOutService { Object.is(inOrOut, MaterialsInOrOutEnum.In) ? this.materialsInventoryService.inInventory.bind(this.materialsInventoryService) : this.materialsInventoryService.outInventory.bind(this.materialsInventoryService) - )({ productId, quantity, unitPrice, projectId, inventoryId, position }, manager); + )({ productId, quantity, unitPrice, projectId, inventoryId, position }, manager, domain); // 2.生成出入库记录 const { id } = await manager.save(MaterialsInOutEntity, { ...this.materialsInOutRepository.create({ ...dto, inventoryId: inventoryEntity?.id }), diff --git a/src/modules/materials_inventory/materials_inventory.controller.ts b/src/modules/materials_inventory/materials_inventory.controller.ts index d7392e4..8e53f13 100644 --- a/src/modules/materials_inventory/materials_inventory.controller.ts +++ b/src/modules/materials_inventory/materials_inventory.controller.ts @@ -45,8 +45,8 @@ export class MaterialsInventoryController { @ApiOperation({ summary: '获取原材料库存列表' }) @ApiResult({ type: [MaterialsInventoryEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: MaterialsInventoryQueryDto) { - return this.miService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: MaterialsInventoryQueryDto) { + return this.miService.findAll({ ...dto, domain }); } @Get(':id') diff --git a/src/modules/materials_inventory/materials_inventory.dto.ts b/src/modules/materials_inventory/materials_inventory.dto.ts index 5d4d89f..b05e466 100644 --- a/src/modules/materials_inventory/materials_inventory.dto.ts +++ b/src/modules/materials_inventory/materials_inventory.dto.ts @@ -61,9 +61,14 @@ export class MaterialsInventoryExportDto extends DomainType { // 开始和结束时间用的是一月的开始和一月的结束的时分秒 const date = params.value; return [ - date ? `${formatToDate(dayjs(date).startOf('month'))} 00:00:00` : null, - date ? `${formatToDate(dayjs(date).endOf('month'))} 23:59:59` : null + date ? `${date[0]} 00:00:00` : null, + date ? `${date[1]} 23:59:59` : null ]; }) time?: string[]; + + @ApiProperty({ description: '文件名' }) + @IsOptional() + @IsString() + filename: string; } diff --git a/src/modules/materials_inventory/materials_inventory.service.ts b/src/modules/materials_inventory/materials_inventory.service.ts index a87d29a..a8b0516 100644 --- a/src/modules/materials_inventory/materials_inventory.service.ts +++ b/src/modules/materials_inventory/materials_inventory.service.ts @@ -23,6 +23,7 @@ import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; import { ParamConfigEntity } from '../system/param-config/param-config.entity'; import { isDefined } from 'class-validator'; +import { DomainType } from '~/common/decorators/domain.decorator'; @Injectable() export class MaterialsInventoryService { constructor( @@ -35,7 +36,7 @@ export class MaterialsInventoryService { private projectRepository: Repository, @InjectRepository(ParamConfigEntity) private paramConfigRepository: Repository - ) {} + ) { } /** * 导出原材料盘点表 @@ -55,7 +56,8 @@ export class MaterialsInventoryService { const inventoriesInProjects = await this.materialsInventoryRepository.find({ where: { ...(projects?.length ? { projectId: In(projects.map(item => item.id)) } : null) - } + }, + relations: ['product', 'product.company', 'product.unit'] }); // 生成数据 @@ -86,7 +88,7 @@ export class MaterialsInventoryService { const data = await sqb.addOrderBy('mio.time', 'DESC').getMany(); if (!projectId) { projects = uniqBy( - data.map(item => item.project), + data.filter(item => item.inOrOut === MaterialsInOrOutEnum.Out).map(item => item.project), 'id' ); } @@ -95,7 +97,9 @@ export class MaterialsInventoryService { const currentProjectInventories = inventoriesInProjects.filter(({ projectId }) => Object.is(projectId, project.id) ); - const currentProjectData = data.filter(item => item.projectId === project.id); + const currentProjectData = data.filter( + item => item.projectId === project.id || item.inOrOut === MaterialsInOrOutEnum.Out + ); const currentMonthProjectData = currentProjectData.filter(item => { return ( dayjs(item.time).isAfter(dayjs(time[0])) && dayjs(item.time).isBefore(dayjs(time[1])) @@ -110,7 +114,7 @@ export class MaterialsInventoryService { sheet.getCell('A2').value = `日期:${dayjs(time[0]).format('YYYY年M月')}`; // 设置表头 const headers = [ - '出入库单号', + '序号', '公司名称', '产品名称', '单位', @@ -128,8 +132,6 @@ export class MaterialsInventoryService { '结存数量', '单价', '金额', - '经办人', - '领料单号', '备注' ]; sheet.addRow(headers); @@ -152,8 +154,6 @@ export class MaterialsInventoryService { '', '', '', - '', - '', '' ]); for (let i = 1; i <= 7; i++) { @@ -175,7 +175,7 @@ export class MaterialsInventoryService { }; } - for (let i = 16; i <= 21; i++) { + for (let i = 16; i <= 19; i++) { sheet.mergeCells(`${String.fromCharCode(64 + i)}3:${String.fromCharCode(64 + i)}4`); } @@ -196,24 +196,40 @@ export class MaterialsInventoryService { } }); + // 根据库存Id分组 const groupedData = groupBy( currentMonthProjectData, - record => `${record.productId}-${record.unitPrice}` + record => record.inventoryId ); let number = 0; - const groupedInventories = groupBy( - currentProjectInventories, - item => `${item.projectId}_${item.productId}` - ); - for (const key in groupedData) { - // 目前暂定逻辑出库只有一次或者没有出库。不会对一个入库的记录多次出库,故而用find。 - const inRecord = groupedData[key].find(item => item.inOrOut === MaterialsInOrOutEnum.In); - const outRecord = groupedData[key].find(item => item.inOrOut === MaterialsInOrOutEnum.Out); - const currInventories = - groupedInventories[`${inRecord.projectId}_${inRecord.productId}`]?.shift(); - const allDataFromMonth = data.filter( - res => res.projectId === inRecord.projectId && res.productId === inRecord.productId + const groupedInventories = groupBy(currentProjectInventories, item => item.id); + let orderNo = 0; + + for (const key in groupedInventories) { + orderNo++; + // 目前暂定逻辑出库只有一次或者没有出库。不会对一个入库的记录多次出库,故而用find。---废弃 + // 2024.04.16 改成 + const inventory = groupedInventories[key][0]; + const outRecords = groupedData[key].filter( + item => item.inOrOut === MaterialsInOrOutEnum.Out ); + const inRecords = groupedData[key].filter(item => item.inOrOut === MaterialsInOrOutEnum.In); + const outRecordQuantity = outRecords + .map(item => item.quantity) + .reduce((acc, cur) => { + return calcNumber(acc, cur, 'add'); + }, 0); + + const inRecordQuantity = inRecords + .map(item => item.quantity) + .reduce((acc, cur) => { + return calcNumber(acc, cur, 'add'); + }, 0); + // 这里的单价默认入库价格和出库价格一致,所以直接用总数量*入库单价 + const outRecordAmount = calcNumber(outRecordQuantity, inventory.unitPrice || 0, 'multiply'); + const inRecordAmount = calcNumber(inRecordQuantity, inventory.unitPrice || 0, 'multiply'); + const currInventories = groupedInventories[key]?.shift(); + const allDataFromMonth = data.filter(res => res.inventoryId == Number(key)); let currentQuantity = 0; let balanceQuantity = 0; // 月初库存数量 @@ -234,32 +250,33 @@ export class MaterialsInventoryService { // 结存库存数量 balanceQuantity = calcNumber( currentQuantity, - calcNumber(inRecord.quantity, outRecord?.quantity || 0, 'subtract'), + calcNumber(inRecordQuantity, outRecordQuantity, 'subtract'), 'add' ); number++; sheet.addRow([ - `${inRecord.inventoryInOutNumber || ''}`, - inRecord.product.company.name || '', - inRecord.product.name || '', - inRecord.product.unit.label || '', + `${orderNo}`, + inventory.product?.company?.name || '', + inventory.product?.name || '', + inventory.product.unit.label || '', currentQuantity, - parseFloat(`${inRecord.unitPrice || 0}`), - calcNumber(currentQuantity, inRecord.unitPrice || 0, 'multiply'), - inRecord.time, - inRecord.quantity || 0, - parseFloat(`${inRecord.unitPrice || 0}`), - parseFloat(`${inRecord.amount || 0}`), - outRecord?.time || '', - outRecord?.quantity || 0, - parseFloat(`${outRecord?.unitPrice || 0}`), - parseFloat(`${outRecord?.amount || 0}`), + parseFloat(`${inventory.unitPrice || 0}`), + calcNumber(currentQuantity, inventory.unitPrice || 0, 'multiply'), + // inRecord.time, + '', + inRecordQuantity, + parseFloat(`${inventory.unitPrice || 0}`), + parseFloat(`${inRecordAmount}`), + // outRecord?.time || '', + '', + outRecordQuantity, + parseFloat(`${inventory?.unitPrice || 0}`), + parseFloat(`${outRecordAmount}`), balanceQuantity, - parseFloat(`${inRecord?.unitPrice || 0}`), - calcNumber(balanceQuantity, inRecord?.unitPrice || 0, 'multiply'), - `${inRecord?.agent || ''}/${outRecord?.agent || ''}`, - outRecord?.issuanceNumber || '', - `${inRecord?.remark || ''}/${outRecord?.remark || ''}` + parseFloat(`${inventory?.unitPrice || 0}`), + calcNumber(balanceQuantity, inventory?.unitPrice || 0, 'multiply'), + // `${inRecord?.agent || ''}/${outRecord?.agent || ''}`, + '' ]); } sheet.getCell('A1').font = { size: HEADER_FONT_SIZE }; @@ -319,7 +336,8 @@ export class MaterialsInventoryService { product, keyword, projectId, - isHasInventory + isHasInventory, + domain }: MaterialsInventoryQueryDto): Promise> { const queryBuilder = this.materialsInventoryRepository .createQueryBuilder('materialsInventory') @@ -339,7 +357,8 @@ export class MaterialsInventoryService { 'product.productSpecification', 'product.productNumber' ]) - .where('materialsInventory.isDelete = 0'); + .where(fieldSearch({ domain })) + .andWhere('materialsInventory.isDelete = 0'); if (product) { queryBuilder.andWhere('product.name like :product', { product: `%${product}%` }); } @@ -402,7 +421,8 @@ export class MaterialsInventoryService { unitPrice?: number; changedUnitPrice?: number; }, - manager: EntityManager + manager: EntityManager, + domain?: DomainType ): Promise { const { projectId, @@ -415,9 +435,9 @@ export class MaterialsInventoryService { } = data; let searchPayload: any = {}; if (isDefined(inventoryId)) { - searchPayload = { id: inventoryId }; + searchPayload = { id: inventoryId, domain }; } else { - searchPayload = { projectId, productId, unitPrice }; + searchPayload = { projectId, productId, unitPrice, domain }; } const exsitedInventory = await manager.findOne(MaterialsInventoryEntity, { where: searchPayload, // 根据项目,产品,价格查出之前的实时库存情况 @@ -461,7 +481,7 @@ export class MaterialsInventoryService { quantity: number; inventoryId?: number; }, - manager: EntityManager + manager: EntityManager, ): Promise { const { quantity: outQuantity, inventoryId } = data; // 开启悲观行锁,防止脏读和修改 diff --git a/src/modules/project/project.controller.ts b/src/modules/project/project.controller.ts index 605090b..bd92a28 100644 --- a/src/modules/project/project.controller.ts +++ b/src/modules/project/project.controller.ts @@ -16,6 +16,7 @@ import { ApiResult } from '~/common/decorators/api-result.decorator'; import { ProjectEntity } from './project.entity'; import { ProjectDto, ProjectQueryDto, ProjectUpdateDto } from './project.dto'; import { IdParam } from '~/common/decorators/id-param.decorator'; +import { Domain, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('app:project', { LIST: 'list', CREATE: 'create', @@ -34,8 +35,8 @@ export class ProjectController { @ApiOperation({ summary: '分页获取项目列表' }) @ApiResult({ type: [ProjectEntity], isPage: true }) @Perm(permissions.LIST) - async list(@Query() dto: ProjectQueryDto) { - return this.projectService.findAll(dto); + async list(@Domain() domain: SkDomain, @Query() dto: ProjectQueryDto) { + return this.projectService.findAll({ ...dto, domain }); } @Get(':id') @@ -49,8 +50,8 @@ export class ProjectController { @Post() @ApiOperation({ summary: '新增项目' }) @Perm(permissions.CREATE) - async create(@Body() dto: ProjectDto): Promise { - await this.projectService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: ProjectDto): Promise { + await this.projectService.create({ ...dto, domain }); } @Put(':id') diff --git a/src/modules/project/project.dto.ts b/src/modules/project/project.dto.ts index 6c96b6e..3e02fc5 100644 --- a/src/modules/project/project.dto.ts +++ b/src/modules/project/project.dto.ts @@ -4,8 +4,9 @@ import { PagerDto } from '~/common/dto/pager.dto'; import { Storage } from '../tools/storage/storage.entity'; import { IsUnique } from '~/shared/database/constraints/unique.constraint'; import { ProjectEntity } from './project.entity'; +import { DomainType } from '~/common/decorators/domain.decorator'; -export class ProjectDto { +export class ProjectDto extends DomainType { @ApiProperty({ description: '项目名称' }) @IsUnique(ProjectEntity, { message: '已存在同名项目' }) @IsString() @@ -31,7 +32,8 @@ export class ComapnyCreateDto extends PartialType(ProjectDto) { export class ProjectQueryDto extends IntersectionType( PagerDto, - PartialType(ProjectDto) + PartialType(ProjectDto), + DomainType ) { @ApiProperty({ description: '项目名称' }) @IsOptional() diff --git a/src/modules/project/project.entity.ts b/src/modules/project/project.entity.ts index a80b296..72a7ec9 100644 --- a/src/modules/project/project.entity.ts +++ b/src/modules/project/project.entity.ts @@ -4,6 +4,7 @@ import { CommonEntity } from '~/common/entity/common.entity'; import { Storage } from '../tools/storage/storage.entity'; import { ProductEntity } from '../product/product.entity'; import { MaterialsInOutEntity } from '../materials_inventory/in_out/materials_in_out.entity'; +import { SkDomain } from '~/common/decorators/domain.decorator'; /** * 项目实体类 @@ -24,6 +25,10 @@ export class ProjectEntity extends CommonEntity { @ApiProperty({ description: '删除状态:0未删除,1已删除' }) isDelete: number; + @Column({ type: 'int', default: 1, comment: '所属域' }) + @ApiProperty({ description: '所属域' }) + domain: SkDomain; + @ApiHideProperty() @OneToMany(() => MaterialsInOutEntity, product => product.project) materialsInOuts: Relation; diff --git a/src/modules/user/dto/user.dto.ts b/src/modules/user/dto/user.dto.ts index f7efc73..24193b5 100644 --- a/src/modules/user/dto/user.dto.ts +++ b/src/modules/user/dto/user.dto.ts @@ -15,10 +15,11 @@ import { ValidateIf } from 'class-validator'; import { isEmpty } from 'lodash'; +import { DomainType } from '~/common/decorators/domain.decorator'; import { PagerDto } from '~/common/dto/pager.dto'; -export class UserDto { +export class UserDto extends DomainType { @ApiProperty({ description: '头像' }) @IsOptional() @IsString() @@ -83,9 +84,9 @@ export class UserDto { status: number; } -export class UserUpdateDto extends PartialType(UserDto) {} +export class UserUpdateDto extends PartialType(UserDto) { } -export class UserQueryDto extends IntersectionType(PagerDto, PartialType(UserDto)) { +export class UserQueryDto extends IntersectionType(PagerDto, PartialType(UserDto), DomainType) { @ApiProperty({ description: '归属大区', example: 1, required: false }) @IsInt() @IsOptional() diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index e844f8b..f09a413 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -22,7 +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'; +import { Domain, DomainType, SkDomain } from '~/common/decorators/domain.decorator'; export const permissions = definePermission('system:user', { LIST: 'list', @@ -42,7 +42,7 @@ export class UserController { constructor( private userService: UserService, private menuService: MenuService - ) {} + ) { } @Get() @ApiOperation({ summary: '获取用户列表' }) @@ -62,8 +62,8 @@ export class UserController { @Post() @ApiOperation({ summary: '新增用户' }) @Perm(permissions.CREATE) - async create(@Body() dto: UserDto): Promise { - await this.userService.create(dto); + async create(@Domain() domain: SkDomain, @Body() dto: UserDto): Promise { + await this.userService.create({ ...dto, domain }); } @Put(':id') diff --git a/src/shared/database/field-search/index.ts b/src/shared/database/field-search/index.ts index 8b4d05d..d8bdc44 100644 --- a/src/shared/database/field-search/index.ts +++ b/src/shared/database/field-search/index.ts @@ -4,7 +4,9 @@ import { SkDomain } from '~/common/decorators/domain.decorator'; export const fieldSearch = (entity: Partial): ObjectLiteral => { let result = {}; for (let key in entity) { - if (entity.hasOwnProperty(key)) { + if (key == 'domain') { + result = { ...result, domain: entity['domain'] || -1 }; + } else if (entity.hasOwnProperty(key)) { switch (typeof entity[key]) { case 'number': result = { ...result, ...(isNumber(entity[key]) ? { [key]: entity[key] } : null) };