feat(flyer): add flyer session and selection system
Test Suite / backend-pr-quick (push) Has been skipped
Test Suite / quick-import-pr-quick (push) Has been skipped
Test Suite / backend-full (push) Successful in 2m49s
Test Suite / flutter-quality (push) Successful in 2m0s

- Add FlyerSession, FlyerItem, and FlyerSelection models to Prisma schema
- Implement session persistence with weekly key generation in FlyerImportService
- Add FlyerSelectionModule to AppModule
- Extend FlyerImportResponse with sessionId and flyerItemId fields
- Create new flyer-selection module directory structure
- Add migration for flyer session and selection tables

BREAKING CHANGE: Flyer import now persists data to FlyerSession and FlyerItem tables
This commit is contained in:
Nils-Johan Gynther
2026-05-18 19:02:32 +02:00
parent a31aff7c35
commit 24a96c3da1
11 changed files with 619 additions and 9 deletions
@@ -0,0 +1,38 @@
import { Type } from 'class-transformer';
import {
IsIn,
IsInt,
IsNumber,
IsOptional,
IsString,
MaxLength,
Min,
} from 'class-validator';
export class CreateFlyerSelectionDto {
@Type(() => Number)
@IsInt()
@Min(1)
itemId!: number;
@IsOptional()
@Type(() => Number)
@IsNumber({ maxDecimalPlaces: 2 })
@Min(0)
plannedQuantity?: number;
@IsOptional()
@IsString()
@MaxLength(24)
plannedUnit?: string;
@IsOptional()
@IsString()
@IsIn(['low', 'normal', 'high'])
priority?: string;
@IsOptional()
@IsString()
@MaxLength(500)
note?: string;
}
@@ -0,0 +1,22 @@
export type FlyerSelectionResponse = {
id: number;
sessionId: number;
itemId: number;
userId: number;
plannedQuantity: number | null;
plannedUnit: string | null;
priority: string;
note: string | null;
status: string;
createdAt: string;
updatedAt: string;
item: {
id: number;
rawName: string;
normalizedName: string;
price: number | null;
priceUnit: string | null;
matchedProductId: number | null;
matchedProductName: string | null;
};
};
@@ -0,0 +1,37 @@
import { Type } from 'class-transformer';
import {
IsIn,
IsNumber,
IsOptional,
IsString,
MaxLength,
Min,
} from 'class-validator';
export class UpdateFlyerSelectionDto {
@IsOptional()
@Type(() => Number)
@IsNumber({ maxDecimalPlaces: 2 })
@Min(0)
plannedQuantity?: number;
@IsOptional()
@IsString()
@MaxLength(24)
plannedUnit?: string;
@IsOptional()
@IsString()
@IsIn(['low', 'normal', 'high'])
priority?: string;
@IsOptional()
@IsString()
@IsIn(['planned', 'bought', 'skipped', 'archived'])
status?: string;
@IsOptional()
@IsString()
@MaxLength(500)
note?: string;
}