BUR-61 current.value сделан nullable в бд. Соответствующие сущности скорректированы под изменение бд

This commit is contained in:
Первов Артем
2026-07-05 22:03:47 +03:00
parent 387f6c0613
commit 22529ba0e8
8 changed files with 31 additions and 17 deletions

View File

@@ -0,0 +1,2 @@
ALTER TABLE current
ALTER COLUMN value DROP NOT NULL;

View File

@@ -0,0 +1,11 @@
import { applyDecorators } from '@nestjs/common';
import { Transform } from 'class-transformer';
import { IsNumber, ValidateIf, ValidationOptions } from 'class-validator';
export function IsNullableNumber(options?: ValidationOptions): PropertyDecorator {
return applyDecorators(
Transform(({ value }) => (value === null ? null : Number(value))),
ValidateIf((_, value) => value !== null),
IsNumber({}, options),
);
}

View File

@@ -1,7 +1,7 @@
export type CurrentRow = {
edge: string;
tag: string;
value: number;
value: number | null;
createdAt: Date;
updatedAt: Date;
name: string | null;

View File

@@ -1,7 +1,7 @@
export type CurrentItemDto = {
edge: string;
tag: string;
value: number;
value: number | null;
createdAt: Date;
updatedAt: Date;
time: Date;

View File

@@ -5,5 +5,5 @@ export class IngestEdgeValuesDto {
timestamp!: string;
@IsObject()
values!: Record<string, number>;
values!: Record<string, number | null>;
}

View File

@@ -1,5 +1,5 @@
import { Type } from 'class-transformer';
import { IsDateString, IsNotEmpty, IsNumber, IsString } from 'class-validator';
import { IsDateString, IsNotEmpty, IsString } from 'class-validator';
import { IsNullableNumber } from '../../common/is-nullable-number.decorator';
export class IngestPointDto {
@IsNotEmpty()
@@ -13,7 +13,6 @@ export class IngestPointDto {
@IsDateString()
timestamp!: string;
@Type(() => Number)
@IsNumber()
value!: number;
@IsNullableNumber()
value!: number | null;
}

View File

@@ -22,7 +22,7 @@ export class IngestController {
const points = Object.entries(body.values).map(([tag, value]) => ({
edge,
tag,
value: Number(value),
value: value === null ? null : Number(value),
timestamp: body.timestamp,
}));

View File

@@ -10,15 +10,17 @@ type IngestResult = {
export class IngestService {
constructor(private readonly db: DbService) {}
/** Пишет одну входящую точку в history и обновляет текущий снимок current для UI/SSE. */
/** Пишет числовую точку в history и всегда обновляет текущий снимок current для UI/SSE. */
async ingestPoint(point: IngestPointDto): Promise<IngestResult> {
await this.db.query(
`
INSERT INTO history (timestamp, edge, tag, value)
VALUES ($1, $2, $3, $4)
`,
[point.timestamp, point.edge, point.tag, point.value],
);
if (point.value !== null) {
await this.db.query(
`
INSERT INTO history (timestamp, edge, tag, value)
VALUES ($1, $2, $3, $4)
`,
[point.timestamp, point.edge, point.tag, point.value],
);
}
await this.db.query(
`