diff --git a/README.md b/README.md index 774412d..af27223 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ pnpm migration:revert 4.执行sql覆盖docker中的数据库 ```bash -docker exec -i huaxin-admin-mysql mysql -h 127.0.0.1 -u root -phuaxin123 hxoa < hxoa_2024-03-05_151242.sql +docker exec -i huaxin-admin-mysql mysql -h 127.0.0.1 -u root -phuaxin123 hxoa < hxoa_2024-03-05_222748.sql ``` 更多细节,请移步至[官方文档](https://typeorm.io/migrations) diff --git a/src/helper/paginate/pagination.ts b/src/helper/paginate/pagination.ts index 1d52aba..02d97c2 100644 --- a/src/helper/paginate/pagination.ts +++ b/src/helper/paginate/pagination.ts @@ -4,7 +4,7 @@ import { IPaginationMeta } from './interface'; export class Pagination { constructor( - public readonly items: PaginationObject[], + public items: PaginationObject[], public readonly meta: T ) {} 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 4c04489..8f999b1 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 @@ -13,6 +13,7 @@ import { Matches, MinLength } from 'class-validator'; +import dayjs from 'dayjs'; import { PagerDto } from '~/common/dto/pager.dto'; import { MaterialsInOrOutEnum } from '~/constants/enum'; import { Storage } from '~/modules/tools/storage/storage.entity'; @@ -21,12 +22,12 @@ import { formatToDate } from '~/utils'; export class MaterialsInOutDto { @ApiProperty({ description: '产品' }) @IsNumber() - product: number; + productId: number; @ApiProperty({ description: '单位(字典)' }) @IsNumber() @IsOptional() - unit: number; + unitId: number; @ApiProperty({ description: '入库或出库 0:入库 1:出库' }) @IsEnum(MaterialsInOrOutEnum) @@ -82,15 +83,24 @@ export class MaterialsInOutUpdateDto extends PartialType(MaterialsInOutDto) { export class MaterialsInOutQueryDto extends PagerDto { @ApiProperty({ description: '出入库时间YYYY-MM-DD' }) @IsOptional() - @IsArray() + // @IsString() @Transform(params => { // 开始和结束时间用的是一天的开始和一天的结束的时分秒 - const [start, end] = params.value; + const date = params.value; return [ - start ? `${formatToDate(start)} 00:00:00` : null, - end ? `${formatToDate(end)} 23:59:59` : null + date ? `${formatToDate(dayjs(date).startOf('month'))} 00:00:00` : null, + date ? `${formatToDate(dayjs(date).endOf('month'))} 23:59:59` : null ]; }) time?: string[]; + @ApiProperty({ description: '入库或出库 0:入库 1:出库' }) + @IsOptional() + @IsEnum(MaterialsInOrOutEnum) + inOrOut: MaterialsInOrOutEnum; + + @ApiProperty({ description: '产品名称' }) + @IsOptional() + @IsString() + product: string; } 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 d2e715a..d3b2cae 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 @@ -1,26 +1,30 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Column, Entity, JoinTable, ManyToMany, Relation } from 'typeorm'; +import { ApiHideProperty, ApiProperty } from '@nestjs/swagger'; +import { + Column, + Entity, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + Relation, + VirtualColumn +} from 'typeorm'; import { CommonEntity } from '~/common/entity/common.entity'; import { MaterialsInOrOutEnum } from '~/constants/enum'; +import { ProductEntity } from '~/modules/product/product.entity'; +import { DictItemEntity } from '~/modules/system/dict-item/dict-item.entity'; import { Storage } from '~/modules/tools/storage/storage.entity'; @Entity({ name: 'materials_in_out' }) export class MaterialsInOutEntity extends CommonEntity { @Column({ - name: 'product', + name: 'product_id', type: 'int', - comment: '产品名称' + comment: '产品' }) - @ApiProperty({ description: '产品名称' }) - product: number; - - @Column({ - name: 'unit', - type: 'int', - comment: '单位(字典)' - }) - @ApiProperty({ description: '单位(字典)' }) - unit: number; + @ApiProperty({ description: '产品' }) + productId: number; @Column({ name: 'inOrOut', @@ -78,6 +82,7 @@ export class MaterialsInOutEntity extends CommonEntity { name: 'issuance_number', type: 'varchar', length: 100, + nullable: true, comment: '领料单号' }) @ApiProperty({ description: '领料单号' }) @@ -95,6 +100,13 @@ export class MaterialsInOutEntity extends CommonEntity { @ApiProperty({ description: '删除状态:0未删除,1已删除' }) isDelete: number; + @ManyToOne(() => ProductEntity) + @JoinColumn({ name: 'product_id' }) + product: ProductEntity; + + @ApiHideProperty() + unit: DictItemEntity; + @ManyToMany(() => Storage, storage => storage.materialsInOut) @JoinTable({ name: 'materials_in_out_storage', 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 65578c0..5e17ee4 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 @@ -7,7 +7,11 @@ import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; import { paginate } from '~/helper/paginate'; import { Storage } from '~/modules/tools/storage/storage.entity'; -import { MaterialsInOutQueryDto, MaterialsInOutDto, MaterialsInOutUpdateDto } from './materials_in_out.dto'; +import { + MaterialsInOutQueryDto, + MaterialsInOutDto, + MaterialsInOutUpdateDto +} from './materials_in_out.dto'; import { MaterialsInOutEntity } from './materials_in_out.entity'; import { fieldSearch } from '~/shared/database/field-search'; @@ -26,25 +30,32 @@ export class MaterialsInOutService { async findAll({ page, pageSize, + product: productName, ...ext }: MaterialsInOutQueryDto): Promise> { - const queryBuilder = this.materialsInOutRepository + const sqb = this.materialsInOutRepository .createQueryBuilder('materialsInOut') .leftJoin('materialsInOut.files', 'files') - .addSelect(['files.id', 'files.path']) - // .where({ - // ...(materialsInOutNumber ? { materialsInOutNumber: Like(`%${materialsInOutNumber}%`) } : null), - // ...(title ? { title: Like(`%${title}%`) } : null), - // ...(isNumber(type) ? { type } : null), - // ...(isNumber(status) ? { status } : null) - // }) + .leftJoin('materialsInOut.product', 'product') + .leftJoin('product.unit', 'unit') + .addSelect(['files.id', 'files.path', 'product.id', 'product.name', 'unit.id', 'unit.label']) .where(fieldSearch(ext)) - .andWhere('materialsInOut.isDelete = 0'); - - return paginate(queryBuilder, { + .andWhere('materialsInOut.isDelete = 0') + .addOrderBy('materialsInOut.time', 'DESC'); + if (productName) { + sqb.andWhere('product.name like :productName', { productName: `%${productName}%` }); + } + let pageData = await paginate(sqb, { page, pageSize }); + // 产品表中的单位字段需要单独处理 + pageData.items = pageData.items.map(materialsInOut => { + materialsInOut.unit = materialsInOut.product.unit; + delete materialsInOut.product.unit; + return materialsInOut; + }); + return pageData; } /** diff --git a/src/modules/product/product.dto.ts b/src/modules/product/product.dto.ts index 4e17d7a..4824c24 100644 --- a/src/modules/product/product.dto.ts +++ b/src/modules/product/product.dto.ts @@ -1,26 +1,18 @@ import { ApiProperty, IntersectionType, PartialType } from '@nestjs/swagger'; -import { - IsArray, - IsDate, - IsDateString, - IsIn, - IsInt, - IsNumber, - IsOptional, - IsString, - Matches, - MinLength -} from 'class-validator'; +import { IsArray, IsNumber, IsOptional, IsString } from 'class-validator'; import { PagerDto } from '~/common/dto/pager.dto'; import { Storage } from '../tools/storage/storage.entity'; -import { IsUnique } from '~/shared/database/constraints/unique.constraint'; -import { ProductEntity } from './product.entity'; export class ProductDto { @ApiProperty({ description: '产品名称' }) @IsString() name: string; + @ApiProperty({ description: '单位(字典)' }) + @IsOptional() + @IsNumber() + unitId: number; + @ApiProperty({ description: '所属公司' }) @IsOptional() @IsNumber() diff --git a/src/modules/product/product.entity.ts b/src/modules/product/product.entity.ts index a5781ed..0c6aa58 100644 --- a/src/modules/product/product.entity.ts +++ b/src/modules/product/product.entity.ts @@ -14,6 +14,7 @@ import { CommonEntity } from '~/common/entity/common.entity'; 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'; @Entity({ name: 'product' }) export class ProductEntity extends CommonEntity { @Column({ @@ -33,6 +34,14 @@ export class ProductEntity extends CommonEntity { @ApiProperty({ description: '所属公司' }) companyId: number; + @Column({ name: 'unit_id', type: 'int', comment: '单位(字典)', nullable: true }) + @ApiProperty({ description: '单位(字典)' }) + unitId: number; + + @ManyToOne(() => DictItemEntity) + @JoinColumn({ name: 'unit_id' }) + unit: DictItemEntity; + @ApiHideProperty() @Column({ name: 'name_pinyin', @@ -46,7 +55,6 @@ export class ProductEntity extends CommonEntity { @BeforeInsert() @BeforeUpdate() updateNamePinyin() { - console.log('sssssssssssssss') this.namePinyin = pinyin(this.name, { style: pinyin.STYLE_NORMAL, heteronym: false diff --git a/src/modules/product/product.service.ts b/src/modules/product/product.service.ts index 585a3f4..5428a3e 100644 --- a/src/modules/product/product.service.ts +++ b/src/modules/product/product.service.ts @@ -33,7 +33,8 @@ export class ProductService { .createQueryBuilder('product') .leftJoin('product.files', 'files') .leftJoin('product.company', 'company') - .addSelect(['files.id', 'files.path', 'company.name', 'company.id']) + .leftJoin('product.unit', 'unit') + .addSelect(['files.id', 'files.path', 'company.name', 'company.id','unit.id','unit.label']) .where(fieldSearch(ext)) .andWhere('product.isDelete = 0') .addOrderBy('product.namePinyin', 'ASC'); diff --git a/src/shared/database/field-search/index.ts b/src/shared/database/field-search/index.ts index dbee970..1067765 100644 --- a/src/shared/database/field-search/index.ts +++ b/src/shared/database/field-search/index.ts @@ -18,7 +18,7 @@ export const fieldSearch = (entity: Partial): ObjectLiteral => { if (Array.isArray(entity[key])) { result = { ...result, - ...(entity[key] && { createdAt: Between(entity[key][0], entity[key][1]) }) + ...(entity[key] && { [key]: Between(entity[key][0], entity[key][1]) }) }; } else { // Handle other object types