From b208f52fd1b79c72aff30af5aa0c13324f73ca09 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Wed, 9 Sep 2026 11:05:13 +0200 Subject: [PATCH] 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 --- .../src/extractions/dto/create-extraction.dto.ts | 5 +++++ .../src/feedings/dto/create-feeding.dto.ts | 2 ++ .../src/harvests/dto/create-harvest.dto.ts | 4 ++++ .../src/honey-batches/dto/create-honey-batch.dto.ts | 5 ++++- .../honey-batches/dto/create-honey-measurement.dto.ts | 11 ++++++++++- .../src/storage/dto/create-stock-item.dto.ts | 4 +++- .../src/varroa/dto/create-varroa-measurement.dto.ts | 4 ++++ 7 files changed, 32 insertions(+), 3 deletions(-) diff --git a/ApiCore-Backend/src/extractions/dto/create-extraction.dto.ts b/ApiCore-Backend/src/extractions/dto/create-extraction.dto.ts index ada16de..69ab7c1 100644 --- a/ApiCore-Backend/src/extractions/dto/create-extraction.dto.ts +++ b/ApiCore-Backend/src/extractions/dto/create-extraction.dto.ts @@ -6,6 +6,8 @@ import { IsNumber, IsOptional, IsString, + Max, + Min, } from 'class-validator'; export class CreateExtractionDto { @@ -22,6 +24,7 @@ export class CreateExtractionDto { @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) amount?: number; @ApiPropertyOptional() @@ -32,6 +35,8 @@ export class CreateExtractionDto { @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) + @Max(100) waterContent?: number; @ApiPropertyOptional() diff --git a/ApiCore-Backend/src/feedings/dto/create-feeding.dto.ts b/ApiCore-Backend/src/feedings/dto/create-feeding.dto.ts index b1e6dd6..9bad53b 100644 --- a/ApiCore-Backend/src/feedings/dto/create-feeding.dto.ts +++ b/ApiCore-Backend/src/feedings/dto/create-feeding.dto.ts @@ -5,6 +5,7 @@ import { IsNumber, IsOptional, IsString, + Min, } from 'class-validator'; import { FeedType } from '../../../generated/prisma'; @@ -28,6 +29,7 @@ export class CreateFeedingDto { @ApiProperty() @IsNumber() + @Min(0) amount!: number; @ApiProperty() diff --git a/ApiCore-Backend/src/harvests/dto/create-harvest.dto.ts b/ApiCore-Backend/src/harvests/dto/create-harvest.dto.ts index c1f606c..100f3b1 100644 --- a/ApiCore-Backend/src/harvests/dto/create-harvest.dto.ts +++ b/ApiCore-Backend/src/harvests/dto/create-harvest.dto.ts @@ -7,6 +7,7 @@ import { IsNumber, IsOptional, IsString, + Min, } from 'class-validator'; export class CreateHarvestDto { @@ -32,16 +33,19 @@ export class CreateHarvestDto { @ApiPropertyOptional() @IsOptional() @IsInt() + @Min(0) honeySuperCount?: number; @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) grossWeight?: number; @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) netWeight?: number; @ApiPropertyOptional() diff --git a/ApiCore-Backend/src/honey-batches/dto/create-honey-batch.dto.ts b/ApiCore-Backend/src/honey-batches/dto/create-honey-batch.dto.ts index c20debd..2a82372 100644 --- a/ApiCore-Backend/src/honey-batches/dto/create-honey-batch.dto.ts +++ b/ApiCore-Backend/src/honey-batches/dto/create-honey-batch.dto.ts @@ -1,5 +1,5 @@ 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 { @ApiPropertyOptional({ @@ -22,11 +22,14 @@ export class CreateHoneyBatchDto { @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) amount?: number; @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) + @Max(100) waterContent?: number; @ApiPropertyOptional() diff --git a/ApiCore-Backend/src/honey-batches/dto/create-honey-measurement.dto.ts b/ApiCore-Backend/src/honey-batches/dto/create-honey-measurement.dto.ts index 1622202..1e90c44 100644 --- a/ApiCore-Backend/src/honey-batches/dto/create-honey-measurement.dto.ts +++ b/ApiCore-Backend/src/honey-batches/dto/create-honey-measurement.dto.ts @@ -1,9 +1,18 @@ 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 { @ApiProperty() @IsNumber() + @Min(0) + @Max(100) waterContent!: number; @ApiProperty() diff --git a/ApiCore-Backend/src/storage/dto/create-stock-item.dto.ts b/ApiCore-Backend/src/storage/dto/create-stock-item.dto.ts index f64f1ed..654294a 100644 --- a/ApiCore-Backend/src/storage/dto/create-stock-item.dto.ts +++ b/ApiCore-Backend/src/storage/dto/create-stock-item.dto.ts @@ -1,5 +1,5 @@ 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'; export class CreateStockItemDto { @@ -18,11 +18,13 @@ export class CreateStockItemDto { @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) quantity?: number; @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) minThreshold?: number; @ApiPropertyOptional() diff --git a/ApiCore-Backend/src/varroa/dto/create-varroa-measurement.dto.ts b/ApiCore-Backend/src/varroa/dto/create-varroa-measurement.dto.ts index 571eb39..c83fb3a 100644 --- a/ApiCore-Backend/src/varroa/dto/create-varroa-measurement.dto.ts +++ b/ApiCore-Backend/src/varroa/dto/create-varroa-measurement.dto.ts @@ -6,6 +6,7 @@ import { IsNumber, IsOptional, IsString, + Min, } from 'class-validator'; import { VarroaMethod } from '../../../generated/prisma'; @@ -25,16 +26,19 @@ export class CreateVarroaMeasurementDto { @ApiPropertyOptional() @IsOptional() @IsInt() + @Min(0) durationMinutes?: number; @ApiPropertyOptional() @IsOptional() @IsInt() + @Min(0) miteCount?: number; @ApiPropertyOptional() @IsOptional() @IsNumber() + @Min(0) calculatedValue?: number; @ApiPropertyOptional()