Commit 971f1c8e authored by nanahira's avatar nanahira

adapt

parent 69cf9949
Pipeline #7149 passed with stages
in 1 minute and 28 seconds
import { ConsoleLogger } from '@nestjs/common'; import { ConsoleLogger } from '@nestjs/common';
import { ClassConstructor } from 'class-transformer'; import { ClassConstructor } from 'class-transformer';
import { Repository, SelectQueryBuilder, UpdateResult } from 'typeorm'; import {
IsNull,
Not,
Repository,
SelectQueryBuilder,
UpdateResult,
} from 'typeorm';
import { import {
BlankReturnMessageDto, BlankReturnMessageDto,
ReturnMessageDto, ReturnMessageDto,
} from '../dto/ReturnMessage.dto'; } from '../dto/ReturnMessage.dto';
import { DeletionWise } from '../entities/bases/DeletionBase.entity';
import { QueryWise } from '../entities/interfaces/QueryWise'; import { QueryWise } from '../entities/interfaces/QueryWise';
import { camelCase } from 'typeorm/util/StringUtils'; import { camelCase } from 'typeorm/util/StringUtils';
import { DeletionWise } from '../entities/bases/TimeBase.entity';
export type EntityId<T> = T extends { id: string } export type EntityId<T> = T extends { id: string }
? string ? string
...@@ -38,13 +44,13 @@ export class CrudBase< ...@@ -38,13 +44,13 @@ export class CrudBase<
const repo = mdb.getRepository(this.entityClass); const repo = mdb.getRepository(this.entityClass);
if (ent.id != null) { if (ent.id != null) {
const existingEnt = await repo.findOne({ const existingEnt = await repo.findOne({
where: { id: ent.id }, where: { id: ent.id, deleteTime: Not(IsNull()) },
take: 1, select: ['id'],
select: ['id', 'isDeleted'], withDeleted: true,
}); });
if (existingEnt) { if (existingEnt) {
if (existingEnt.isDeleted) { if (existingEnt) {
await repo.delete({ id: ent.id }); await repo.delete(existingEnt.id);
} else { } else {
throw new BlankReturnMessageDto( throw new BlankReturnMessageDto(
404, 404,
...@@ -76,11 +82,7 @@ export class CrudBase< ...@@ -76,11 +82,7 @@ export class CrudBase<
: `${relationUnit[relationUnit.length - 2]}_${relationUnit.length - 1}`; : `${relationUnit[relationUnit.length - 2]}_${relationUnit.length - 1}`;
const property = relationUnit[relationUnit.length - 1]; const property = relationUnit[relationUnit.length - 1];
const properyAlias = `${property}_${relationUnit.length}`; const properyAlias = `${property}_${relationUnit.length}`;
qb.leftJoinAndSelect( qb.leftJoinAndSelect(`${base}.${property}`, properyAlias);
`${base}.${property}`,
properyAlias,
`${properyAlias}.isDeleted = false`,
);
} }
protected applyRelationsToQuery(qb: SelectQueryBuilder<T>) { protected applyRelationsToQuery(qb: SelectQueryBuilder<T>) {
...@@ -96,19 +98,12 @@ export class CrudBase< ...@@ -96,19 +98,12 @@ export class CrudBase<
async findOne(id: EntityId<T>) { async findOne(id: EntityId<T>) {
const query = this.queryBuilder() const query = this.queryBuilder()
.where(`${this.entityAliasName}.id = :id`, { id }) .where(`${this.entityAliasName}.id = :id`, { id })
.andWhere(`${this.entityAliasName}.isDeleted = false`)
.take(1); .take(1);
this.applyRelationsToQuery(query); this.applyRelationsToQuery(query);
this.extraGetQuery(query); this.extraGetQuery(query);
let ent: T;
try { try {
const ent = await query.getOne(); ent = await query.getOne();
if (!ent) {
throw new BlankReturnMessageDto(
404,
`ID ${id} not found.`,
).toException();
}
return new ReturnMessageDto(200, 'success', ent);
} catch (e) { } catch (e) {
const [sql, params] = query.getQueryAndParameters(); const [sql, params] = query.getQueryAndParameters();
this.error( this.error(
...@@ -118,6 +113,10 @@ export class CrudBase< ...@@ -118,6 +113,10 @@ export class CrudBase<
); );
throw new BlankReturnMessageDto(500, 'internal error').toException(); throw new BlankReturnMessageDto(500, 'internal error').toException();
} }
if (!ent) {
throw new BlankReturnMessageDto(404, `ID ${id} not found.`).toException();
}
return new ReturnMessageDto(200, 'success', ent);
} }
async findAll(ent?: T) { async findAll(ent?: T) {
...@@ -143,10 +142,10 @@ export class CrudBase< ...@@ -143,10 +142,10 @@ export class CrudBase<
async update(id: EntityId<T>, entPart: Partial<T>) { async update(id: EntityId<T>, entPart: Partial<T>) {
let result: UpdateResult; let result: UpdateResult;
try { try {
result = await this.repo.update({ id, isDeleted: false }, entPart); result = await this.repo.update(id, entPart);
} catch (e) { } catch (e) {
this.error( this.error(
`Failed to create entity ID ${id} to ${JSON.stringify( `Failed to update entity ID ${id} to ${JSON.stringify(
entPart, entPart,
)}: ${e.toString()}`, )}: ${e.toString()}`,
); );
...@@ -161,9 +160,7 @@ export class CrudBase< ...@@ -161,9 +160,7 @@ export class CrudBase<
async remove(id: EntityId<T>) { async remove(id: EntityId<T>) {
let result: UpdateResult; let result: UpdateResult;
try { try {
result = await this.repo.update({ id, isDeleted: false }, { result = await this.repo.softDelete(id);
isDeleted: true,
} as Partial<T>);
} catch (e) { } catch (e) {
this.error(`Failed to delete entity ID ${id}: ${e.toString()}`); this.error(`Failed to delete entity ID ${id}: ${e.toString()}`);
throw new BlankReturnMessageDto(500, 'internal error').toException(); throw new BlankReturnMessageDto(500, 'internal error').toException();
......
import { IsInt, IsOptional, IsPositive } from 'class-validator'; import { IsInt, IsOptional, IsPositive } from 'class-validator';
import { SelectQueryBuilder } from 'typeorm'; import { SelectQueryBuilder } from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';
export class PageSettingsDto { export class PageSettingsDto {
@IsOptional() @IsOptional()
@IsPositive() @IsPositive()
@IsInt() @IsInt()
@ApiProperty({ description: '第 n 页,从 1 开始' })
pageCount: number; pageCount: number;
@IsOptional() @IsOptional()
@IsPositive() @IsPositive()
@IsInt() @IsInt()
@ApiProperty({ description: '每页显示的数量' })
recordsPerPage: number; recordsPerPage: number;
private getRecordsPerPage() { private getRecordsPerPage() {
......
import { TimeBase } from './TimeBase.entity';
import { Column, SelectQueryBuilder } from 'typeorm';
import { Exclude } from 'class-transformer';
export interface DeletionWise {
isDeleted: boolean;
}
export class DeletionBase extends TimeBase implements DeletionWise {
@Column('boolean', { select: false, default: false })
@Exclude()
isDeleted: boolean;
applyQuery(qb: SelectQueryBuilder<DeletionBase>, entityName: string) {
super.applyQuery(qb, entityName);
qb.where(`${entityName}.isDeleted = false`);
}
}
import { DeletionBase } from './DeletionBase.entity';
import { Column, Generated, SelectQueryBuilder } from 'typeorm'; import { Column, Generated, SelectQueryBuilder } from 'typeorm';
import { IdWise } from '../interfaces/wises'; import { IdWise } from '../interfaces/wises';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
...@@ -6,8 +5,9 @@ import { applyQueryProperty } from '../utility/query'; ...@@ -6,8 +5,9 @@ import { applyQueryProperty } from '../utility/query';
import { NotWritable } from '../decorators/transform'; import { NotWritable } from '../decorators/transform';
import { IsInt, IsPositive } from 'class-validator'; import { IsInt, IsPositive } from 'class-validator';
import { BigintTransformer } from '../utility/bigint-transform'; import { BigintTransformer } from '../utility/bigint-transform';
import { TimeBase } from './TimeBase.entity';
export class IdBase extends DeletionBase implements IdWise { export class IdBase extends TimeBase implements IdWise {
@Generated('increment') @Generated('increment')
@Column('bigint', { @Column('bigint', {
primary: true, primary: true,
......
import { PrimaryColumn, SelectQueryBuilder } from 'typeorm'; import { PrimaryColumn, SelectQueryBuilder } from 'typeorm';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { DeletionBase } from './DeletionBase.entity';
import { StringIdWise } from '../interfaces/wises'; import { StringIdWise } from '../interfaces/wises';
import { applyQueryProperty } from '../utility/query'; import { applyQueryProperty } from '../utility/query';
import { NotChangeable } from '../decorators/transform'; import { NotChangeable } from '../decorators/transform';
import { IsNotEmpty, IsString } from 'class-validator'; import { IsNotEmpty, IsString } from 'class-validator';
import { TimeBase } from './TimeBase.entity';
export class ManualIdBase extends DeletionBase implements StringIdWise { export class ManualIdBase extends TimeBase implements StringIdWise {
@PrimaryColumn('varchar', { length: 32 }) @PrimaryColumn('varchar', { length: 32 })
@ApiProperty({ description: '编号' }) @ApiProperty({ description: '编号' })
@NotChangeable() @NotChangeable()
......
import { CreateDateColumn, UpdateDateColumn } from 'typeorm'; import { CreateDateColumn, DeleteDateColumn, UpdateDateColumn } from 'typeorm';
import { Exclude } from 'class-transformer'; import { Exclude } from 'class-transformer';
import { PageSettingsDto } from '../../dto/PageSettings.dto'; import { PageSettingsDto } from '../../dto/PageSettings.dto';
export class TimeBase extends PageSettingsDto { export interface DeletionWise {
deleteTime?: Date;
}
export class TimeBase extends PageSettingsDto implements DeletionWise {
@CreateDateColumn({ select: false }) @CreateDateColumn({ select: false })
@Exclude() @Exclude()
createTime: Date; createTime: Date;
...@@ -11,6 +15,10 @@ export class TimeBase extends PageSettingsDto { ...@@ -11,6 +15,10 @@ export class TimeBase extends PageSettingsDto {
@Exclude() @Exclude()
updateTime: Date; updateTime: Date;
@DeleteDateColumn({ select: false })
@Exclude()
deleteTime: Date;
toObject() { toObject() {
return JSON.parse(JSON.stringify(this)); return JSON.parse(JSON.stringify(this));
} }
......
import { ApiProperty } from '@nestjs/swagger';
import { HttpException } from '@nestjs/common';
export interface BlankReturnMessage {
statusCode: number;
message: string;
success: boolean;
}
export interface ReturnMessage<T> extends BlankReturnMessage {
data?: T;
}
export class BlankReturnMessageDto implements BlankReturnMessage {
@ApiProperty({ description: '返回状态' })
statusCode: number;
@ApiProperty({ description: '返回信息' })
message: string;
@ApiProperty({ description: '是否成功' })
success: boolean;
constructor(statusCode: number, message?: string) {
this.statusCode = statusCode;
this.message = message || 'success';
this.success = statusCode < 400;
}
toException() {
return new HttpException(this, this.statusCode);
}
}
export class ReturnMessageDto<T>
extends BlankReturnMessageDto
implements ReturnMessage<T> {
@ApiProperty({ description: '返回内容' })
data?: T;
constructor(statusCode: number, message?: string, data?: T) {
super(statusCode, message);
this.data = data;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment