fix: reject negative weights/quantities and out-of-range percentages

None of these numeric business fields had a lower bound, so a
negative honey weight, jar count, feeding amount, mite count, or
stock quantity was silently accepted - each would corrupt whatever
total or statistic it later feeds into. Added @Min(0):

- Harvest: honeySuperCount, grossWeight, netWeight
- HoneyBatch: amount (+ @Max(100) on waterContent, a percentage)
- HoneyMeasurement: waterContent (+ @Max(100))
- Feeding: amount
- Extraction: amount (+ @Max(100) on waterContent)
- StockItem: quantity, minThreshold
- VarroaMeasurement: durationMinutes, miteCount, calculatedValue

Left temperature fields alone (extraction, inspection) - genuinely
can be negative (winter inspections, outdoor storage) and no
confident domain bound exists to apply instead. Update DTOs for these
entities all extend PartialType(PickType(Create...Dto, [...])) from
@nestjs/swagger, which preserves validation decorators, so no
separate change was needed there.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Sonnet 5 committed 2026-09-09 11:05:13 +02:00
1 parent 93d0f2b208
commit b208f52fd1
7 files changed
+32 -3

No files matched your search

@@ -6,6 +6,8 @@ import {
IsNumber, IsNumber,
IsOptional, IsOptional,
IsString, IsString,
Max,
Min,
} from 'class-validator'; } from 'class-validator';
export class CreateExtractionDto { export class CreateExtractionDto {
@@ -22,6 +24,7 @@ export class CreateExtractionDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
amount?: number; amount?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@@ -32,6 +35,8 @@ export class CreateExtractionDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
@Max(100)
waterContent?: number; waterContent?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@@ -5,6 +5,7 @@ import {
IsNumber, IsNumber,
IsOptional, IsOptional,
IsString, IsString,
Min,
} from 'class-validator'; } from 'class-validator';
import { FeedType } from '../../../generated/prisma'; import { FeedType } from '../../../generated/prisma';
@@ -28,6 +29,7 @@ export class CreateFeedingDto {
@ApiProperty() @ApiProperty()
@IsNumber() @IsNumber()
@Min(0)
amount!: number; amount!: number;
@ApiProperty() @ApiProperty()
@@ -7,6 +7,7 @@ import {
IsNumber, IsNumber,
IsOptional, IsOptional,
IsString, IsString,
Min,
} from 'class-validator'; } from 'class-validator';
export class CreateHarvestDto { export class CreateHarvestDto {
@@ -32,16 +33,19 @@ export class CreateHarvestDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsInt() @IsInt()
@Min(0)
honeySuperCount?: number; honeySuperCount?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
grossWeight?: number; grossWeight?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
netWeight?: number; netWeight?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsNumber, IsOptional, IsString } from 'class-validator'; import { IsNumber, IsOptional, IsString, Max, Min } from 'class-validator';
export class CreateHoneyBatchDto { export class CreateHoneyBatchDto {
@ApiPropertyOptional({ @ApiPropertyOptional({
@@ -22,11 +22,14 @@ export class CreateHoneyBatchDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
amount?: number; amount?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
@Max(100)
waterContent?: number; waterContent?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@@ -1,9 +1,18 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsDateString, IsNumber, IsOptional, IsString } from 'class-validator'; import {
IsDateString,
IsNumber,
IsOptional,
IsString,
Max,
Min,
} from 'class-validator';
export class CreateHoneyMeasurementDto { export class CreateHoneyMeasurementDto {
@ApiProperty() @ApiProperty()
@IsNumber() @IsNumber()
@Min(0)
@Max(100)
waterContent!: number; waterContent!: number;
@ApiProperty() @ApiProperty()
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsEnum, IsNumber, IsOptional, IsString } from 'class-validator'; import { IsEnum, IsNumber, IsOptional, IsString, Min } from 'class-validator';
import { StockCategory } from '../../../generated/prisma'; import { StockCategory } from '../../../generated/prisma';
export class CreateStockItemDto { export class CreateStockItemDto {
@@ -18,11 +18,13 @@ export class CreateStockItemDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
quantity?: number; quantity?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
minThreshold?: number; minThreshold?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@@ -6,6 +6,7 @@ import {
IsNumber, IsNumber,
IsOptional, IsOptional,
IsString, IsString,
Min,
} from 'class-validator'; } from 'class-validator';
import { VarroaMethod } from '../../../generated/prisma'; import { VarroaMethod } from '../../../generated/prisma';
@@ -25,16 +26,19 @@ export class CreateVarroaMeasurementDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsInt() @IsInt()
@Min(0)
durationMinutes?: number; durationMinutes?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsInt() @IsInt()
@Min(0)
miteCount?: number; miteCount?: number;
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@Min(0)
calculatedValue?: number; calculatedValue?: number;
@ApiPropertyOptional() @ApiPropertyOptional()