Allow null price and unlimited stock on store item create/sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-08 15:36:41 +03:30
co-authored by Cursor
parent 5cd762c65d
commit b5a54e4174
2 changed files with 32 additions and 8 deletions
+30 -6
View File
@@ -8,6 +8,7 @@ import {
IsString, IsString,
Min, Min,
MinLength, MinLength,
ValidateIf,
ValidateNested, ValidateNested,
} from 'class-validator'; } from 'class-validator';
@@ -21,21 +22,34 @@ export class StoreItemVariantSelectionDto {
optionId!: string; optionId!: string;
} }
/** Keep null as null; avoid `Number(null) === 0`. */
function nullableNumber({ value }: { value: unknown }) {
if (value === null || value === undefined || value === '') return null;
const n = typeof value === 'number' ? value : Number(value);
return Number.isFinite(n) ? n : value;
}
export class CreateStoreItemVariantDto { export class CreateStoreItemVariantDto {
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@Type(() => StoreItemVariantSelectionDto) @Type(() => StoreItemVariantSelectionDto)
selections!: StoreItemVariantSelectionDto[]; selections!: StoreItemVariantSelectionDto[];
/** null / omitted = contact for price */
@IsOptional() @IsOptional()
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsNumber() @IsNumber()
@Min(0) @Min(0)
price?: number; price?: number | null;
/** null / omitted = unlimited stock */
@IsOptional() @IsOptional()
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsInt() @IsInt()
@Min(0) @Min(0)
stockQuantity?: number; stockQuantity?: number | null;
} }
export class BatchCreateStoreItemsDto { export class BatchCreateStoreItemsDto {
@@ -117,14 +131,18 @@ export class ListPublicStoreItemsDto {
export class UpdateStoreItemVariantDto { export class UpdateStoreItemVariantDto {
@IsOptional() @IsOptional()
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsNumber() @IsNumber()
@Min(0) @Min(0)
price?: number; price?: number | null;
@IsOptional() @IsOptional()
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsInt() @IsInt()
@Min(0) @Min(0)
stockQuantity?: number; stockQuantity?: number | null;
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
@@ -167,13 +185,19 @@ export class SyncStoreItemVariantRowDto {
@Type(() => StoreItemVariantSelectionDto) @Type(() => StoreItemVariantSelectionDto)
selections!: StoreItemVariantSelectionDto[]; selections!: StoreItemVariantSelectionDto[];
/** null = contact for price */
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsNumber() @IsNumber()
@Min(0) @Min(0)
price!: number; price!: number | null;
/** null = unlimited stock */
@Transform(nullableNumber)
@ValidateIf((_, v) => v !== null && v !== undefined)
@IsInt() @IsInt()
@Min(0) @Min(0)
stockQuantity!: number; stockQuantity!: number | null;
} }
export class SyncProductStoreItemVariantsDto { export class SyncProductStoreItemVariantsDto {
+2 -2
View File
@@ -916,11 +916,11 @@ export class StoreItemsService {
existingKeys.add(key); existingKeys.add(key);
batchKeys.add(key); batchKeys.add(key);
if (item.price !== undefined && item.price < 0) { if (item.price != null && item.price < 0) {
throw new BadRequestException('Price cannot be negative'); throw new BadRequestException('Price cannot be negative');
} }
if (item.stockQuantity !== undefined && item.stockQuantity < 0) { if (item.stockQuantity != null && item.stockQuantity < 0) {
throw new BadRequestException('Stock cannot be negative'); throw new BadRequestException('Stock cannot be negative');
} }
} }