feat: Complete PL24 architecture overhaul with email & auth improvements
## PL24 Integration Rewrite - Add dual architecture support: P5 Modern (JSON API) + Legacy (HTML scraping) - New services: factory, session, fetch, html-parser, legacy-scraper - Add NHTSA WMI data for accurate brand detection - Brand-specific parsers for VW, Mercedes, BMW, Audi, Porsche, Ford, etc. - Add 254 schema images for parts diagrams ## Authentication & Security - Add PasswordResetToken database model with proper expiration - Implement dual persistence (Redis + DB) for password reset tokens - Add email enumeration protection ## Email Module - New EmailService for password reset emails - Configurable SMTP settings ## Database Schema - Add Vehicle fields: equipment, interiorCode, productionDate, salesType - Add Part.hotspotId for schema hotspot linking - Add SchemaPic.hotspots JSON field - Add VehicleCategory.subGroupsJson for subgroup data ## Frontend - Improve auth pages (login, register, forgot-password) - Enhance vehicle detail and categories pages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@@ -44,6 +44,11 @@ pnpm test # Tests
|
||||
- Parçaları on-demand çek (kullanıcı kategoriye tıklayınca)
|
||||
- Credentials: `.env` dosyasında
|
||||
|
||||
## Test Kullanıcı
|
||||
|
||||
- **Email**: admin@sase.tr
|
||||
- **Password**: SaseAdmin2024
|
||||
|
||||
## Kod Stili
|
||||
|
||||
- TypeScript strict mode
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
"db:migrate:dev": "prisma migrate dev",
|
||||
"db:seed": "ts-node prisma/seed.ts",
|
||||
"db:studio": "prisma studio",
|
||||
"clean": "rm -rf dist"
|
||||
"clean": "rm -rf dist",
|
||||
"pl24:analyze": "ts-node scripts/pl24_analysis/catalog_explorer.ts",
|
||||
"pl24:test-legacy": "ts-node scripts/pl24_analysis/test_legacy_parsers.ts",
|
||||
"pl24:capture-html": "ts-node scripts/pl24_analysis/legacy_vin_tester.ts",
|
||||
"pl24:direct-test": "ts-node scripts/pl24_analysis/direct_parser_test.ts",
|
||||
"pl24:offline-test": "ts-node scripts/pl24_analysis/offline_parser_test.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^10.4.15",
|
||||
@@ -30,6 +35,7 @@
|
||||
"@nestjs/jwt": "^10.2.0",
|
||||
"@nestjs/passport": "^10.0.3",
|
||||
"@nestjs/platform-express": "^10.4.15",
|
||||
"@nestjs/swagger": "^8.0.0",
|
||||
"@nestjs/throttler": "^6.3.0",
|
||||
"@prisma/client": "^6.1.0",
|
||||
"@sase/shared": "workspace:*",
|
||||
@@ -38,12 +44,17 @@
|
||||
"bullmq": "^5.30.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"css-select": "^5.1.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.1.0",
|
||||
"htmlparser2": "^9.1.0",
|
||||
"ioredis": "^5.4.2",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"puppeteer": "^24.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1",
|
||||
"undici": "^7.2.0",
|
||||
"uuid": "^11.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -8,27 +8,44 @@ datasource db {
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String?
|
||||
avatar String?
|
||||
provider AuthProvider @default(EMAIL)
|
||||
providerId String?
|
||||
passwordHash String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
role Role @default(USER)
|
||||
queryLogs QueryLog[]
|
||||
selectedBrands UserBrand[]
|
||||
subscription UserSubscription?
|
||||
vehicles Vehicle[] @relation("QueriedBy")
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String?
|
||||
avatar String?
|
||||
provider AuthProvider @default(EMAIL)
|
||||
providerId String?
|
||||
passwordHash String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
role Role @default(USER)
|
||||
passwordResetTokens PasswordResetToken[]
|
||||
queryLogs QueryLog[]
|
||||
selectedBrands UserBrand[]
|
||||
subscription UserSubscription?
|
||||
vehicles Vehicle[] @relation("QueriedBy")
|
||||
|
||||
@@index([email])
|
||||
@@index([role])
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model PasswordResetToken {
|
||||
id String @id @default(cuid())
|
||||
tokenHash String @unique
|
||||
userId String
|
||||
expiresAt DateTime
|
||||
isUsed Boolean @default(false)
|
||||
usedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tokenHash])
|
||||
@@index([userId])
|
||||
@@index([expiresAt])
|
||||
@@map("password_reset_tokens")
|
||||
}
|
||||
|
||||
model Brand {
|
||||
id String @id @default(cuid())
|
||||
code String @unique
|
||||
@@ -101,28 +118,32 @@ model UserBrand {
|
||||
}
|
||||
|
||||
model Vehicle {
|
||||
id String @id @default(cuid())
|
||||
vin String @unique @db.VarChar(17)
|
||||
brandId String
|
||||
model String
|
||||
year Int
|
||||
series String?
|
||||
bodyType String?
|
||||
engineCode String?
|
||||
engineType String?
|
||||
engineVolume String?
|
||||
transmission String?
|
||||
driveType String?
|
||||
colorCode String?
|
||||
rawResponse Json
|
||||
queriedById String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
parts Part[]
|
||||
queryLogs QueryLog[]
|
||||
categories VehicleCategory[]
|
||||
brand Brand @relation(fields: [brandId], references: [id])
|
||||
queriedBy User? @relation("QueriedBy", fields: [queriedById], references: [id])
|
||||
id String @id @default(cuid())
|
||||
vin String @unique @db.VarChar(17)
|
||||
brandId String
|
||||
model String
|
||||
year Int
|
||||
series String?
|
||||
bodyType String?
|
||||
engineCode String?
|
||||
engineType String?
|
||||
engineVolume String?
|
||||
transmission String?
|
||||
driveType String?
|
||||
colorCode String?
|
||||
rawResponse Json
|
||||
queriedById String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
equipment Json?
|
||||
interiorCode String?
|
||||
productionDate String?
|
||||
salesType String?
|
||||
parts Part[]
|
||||
queryLogs QueryLog[]
|
||||
categories VehicleCategory[]
|
||||
brand Brand @relation(fields: [brandId], references: [id])
|
||||
queriedBy User? @relation("QueriedBy", fields: [queriedById], references: [id])
|
||||
|
||||
@@index([vin])
|
||||
@@index([brandId])
|
||||
@@ -158,12 +179,13 @@ model VehicleCategory {
|
||||
vehicleId String
|
||||
categoryId String
|
||||
partCount Int @default(0)
|
||||
schemaImageUrl String? @db.Text // Original URL from PL24
|
||||
schemaPicId String? // Reference to deduplicated schema image
|
||||
createdAt DateTime @default(now())
|
||||
schemaImageUrl String? @db.Text
|
||||
schemaPicId String?
|
||||
subGroupsJson Json?
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
schemaPic SchemaPic? @relation(fields: [schemaPicId], references: [id])
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([vehicleId, categoryId])
|
||||
@@index([vehicleId])
|
||||
@@ -173,44 +195,56 @@ model VehicleCategory {
|
||||
}
|
||||
|
||||
model SchemaPic {
|
||||
id String @id @default(cuid())
|
||||
imageId String @unique // PL24 image ID (e.g., "194500200") for deduplication
|
||||
localPath String // Local path: /images/schemas/194500200.png
|
||||
originalUrl String? @db.Text // Original PL24 URL for reference
|
||||
fileSize Int? // File size in bytes
|
||||
width Int? // Image width
|
||||
height Int? // Image height
|
||||
createdAt DateTime @default(now())
|
||||
vehicleCategories VehicleCategory[]
|
||||
id String @id @default(cuid())
|
||||
imageId String @unique
|
||||
localPath String
|
||||
originalUrl String? @db.Text
|
||||
fileSize Int?
|
||||
width Int?
|
||||
height Int?
|
||||
createdAt DateTime @default(now())
|
||||
hotspots Json?
|
||||
vehicleCategories VehicleCategory[]
|
||||
|
||||
@@index([imageId])
|
||||
@@map("schema_pics")
|
||||
}
|
||||
|
||||
model Part {
|
||||
id String @id @default(cuid())
|
||||
vehicleId String
|
||||
categoryId String
|
||||
oemCode String
|
||||
oemCodes Json?
|
||||
nameEn String
|
||||
nameTr String
|
||||
description String? @db.Text
|
||||
positionCode String?
|
||||
positionX Float?
|
||||
positionY Float?
|
||||
brandPrices Json
|
||||
imageUrl String?
|
||||
notes String? @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
id String @id @default(cuid())
|
||||
vehicleId String
|
||||
categoryId String
|
||||
oemCode String
|
||||
oemCodes Json?
|
||||
nameEn String
|
||||
nameTr String
|
||||
description String? @db.Text
|
||||
positionCode String?
|
||||
positionX Float?
|
||||
positionY Float?
|
||||
brandPrices Json
|
||||
imageUrl String?
|
||||
notes String? @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
hotspotId String?
|
||||
modelCodes String? @db.Text
|
||||
quantity Int?
|
||||
remark String?
|
||||
subGroupId String?
|
||||
formattedPartNo String?
|
||||
isPreselected Boolean @default(false)
|
||||
restrictions Json?
|
||||
supersededBy String?
|
||||
supersedes String?
|
||||
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([oemCode])
|
||||
@@index([vehicleId])
|
||||
@@index([categoryId])
|
||||
@@index([vehicleId, categoryId])
|
||||
@@index([subGroupId])
|
||||
@@map("parts")
|
||||
}
|
||||
|
||||
@@ -483,6 +517,251 @@ model EmexCategoryTranslation {
|
||||
@@map("emex_category_translations")
|
||||
}
|
||||
|
||||
model PL24Catalog {
|
||||
id String @id @default(cuid())
|
||||
serviceName String @unique
|
||||
name String
|
||||
brand String
|
||||
catalogBase String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
partGroups PL24PartGroup[]
|
||||
parts PL24Part[]
|
||||
vehicles PL24Vehicle[]
|
||||
|
||||
@@index([brand])
|
||||
@@map("pl24_catalogs")
|
||||
}
|
||||
|
||||
model PL24Vehicle {
|
||||
id String @id @default(cuid())
|
||||
catalogId String
|
||||
vehicleId String
|
||||
name String
|
||||
model String
|
||||
series String?
|
||||
bodyType String?
|
||||
engineCode String?
|
||||
engineType String?
|
||||
engineVolume String?
|
||||
transmission String?
|
||||
driveType String?
|
||||
fuelType String?
|
||||
yearFrom Int?
|
||||
yearTo Int?
|
||||
catalogPath String @db.Text
|
||||
mainGroupsPath String? @db.Text
|
||||
ssd String? @db.VarChar(500)
|
||||
rawSegments Json?
|
||||
uniqueKey String @unique @db.VarChar(255)
|
||||
dataHash String? @db.Char(32)
|
||||
scrapeComplete Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
groupLinks PL24VehicleGroup[]
|
||||
partLinks PL24VehiclePart[]
|
||||
vinLinks PL24VehicleVin[]
|
||||
catalog PL24Catalog @relation(fields: [catalogId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([catalogId])
|
||||
@@index([vehicleId])
|
||||
@@index([model])
|
||||
@@index([engineCode])
|
||||
@@map("pl24_vehicles")
|
||||
}
|
||||
|
||||
model PL24VehicleVin {
|
||||
id String @id @default(cuid())
|
||||
vin String @unique @db.VarChar(17)
|
||||
vehicleId String
|
||||
productionDate String?
|
||||
colorCode String?
|
||||
interiorCode String?
|
||||
transmissionCode String?
|
||||
equipment String? @db.Text
|
||||
salesType String?
|
||||
createdAt DateTime @default(now())
|
||||
vehicle PL24Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([vehicleId])
|
||||
@@map("pl24_vehicle_vins")
|
||||
}
|
||||
|
||||
model PL24PartGroup {
|
||||
id String @id @default(cuid())
|
||||
catalogId String
|
||||
parentId String?
|
||||
groupCode String
|
||||
name String
|
||||
nameTr String?
|
||||
description String? @db.Text
|
||||
level Int @default(1)
|
||||
sortOrder Int @default(0)
|
||||
hasParts Boolean @default(false)
|
||||
hasChildren Boolean @default(false)
|
||||
lft Int?
|
||||
rgt Int?
|
||||
iconUrl String? @db.Text
|
||||
uniqueKey String @unique @db.VarChar(255)
|
||||
dataHash String? @db.Char(32)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
catalog PL24Catalog @relation(fields: [catalogId], references: [id], onDelete: Cascade)
|
||||
parent PL24PartGroup? @relation("PL24GroupTree", fields: [parentId], references: [id])
|
||||
children PL24PartGroup[] @relation("PL24GroupTree")
|
||||
images PL24PartImage[]
|
||||
parts PL24Part[]
|
||||
vehicleLinks PL24VehicleGroup[]
|
||||
vehicleParts PL24VehiclePart[]
|
||||
|
||||
@@index([catalogId])
|
||||
@@index([parentId])
|
||||
@@index([groupCode])
|
||||
@@map("pl24_part_groups")
|
||||
}
|
||||
|
||||
model PL24VehicleGroup {
|
||||
id String @id @default(cuid())
|
||||
vehicleId String
|
||||
groupId String
|
||||
linkPath String? @db.Text
|
||||
linkWid String?
|
||||
partCount Int @default(0)
|
||||
isScraped Boolean @default(false)
|
||||
schemaImageUrl String? @db.Text
|
||||
schemaPicId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
group PL24PartGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
||||
schemaPic PL24SchemaPic? @relation(fields: [schemaPicId], references: [id])
|
||||
vehicle PL24Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([vehicleId, groupId])
|
||||
@@index([vehicleId])
|
||||
@@index([groupId])
|
||||
@@index([schemaPicId])
|
||||
@@map("pl24_vehicle_groups")
|
||||
}
|
||||
|
||||
model PL24Part {
|
||||
id String @id @default(cuid())
|
||||
catalogId String
|
||||
groupId String?
|
||||
partNumber String @db.VarChar(50)
|
||||
partNumberClean String? @db.VarChar(50)
|
||||
formattedPartNo String?
|
||||
name String
|
||||
nameTr String?
|
||||
description String? @db.Text
|
||||
brand String?
|
||||
quantity Float @default(1)
|
||||
unit String @default("PC")
|
||||
positionCode String?
|
||||
positionX Float?
|
||||
positionY Float?
|
||||
remark String? @db.Text
|
||||
modelCodes String? @db.Text
|
||||
notes String? @db.Text
|
||||
uniqueKey String @unique @db.VarChar(255)
|
||||
dataHash String? @db.Char(32)
|
||||
isActive Boolean @default(true)
|
||||
isDiscontinued Boolean @default(false)
|
||||
supersededById String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
altNumbers PL24PartNumber[]
|
||||
catalog PL24Catalog @relation(fields: [catalogId], references: [id], onDelete: Cascade)
|
||||
group PL24PartGroup? @relation(fields: [groupId], references: [id])
|
||||
vehicleLinks PL24VehiclePart[]
|
||||
|
||||
@@index([catalogId])
|
||||
@@index([groupId])
|
||||
@@index([partNumber])
|
||||
@@index([partNumberClean])
|
||||
@@map("pl24_parts")
|
||||
}
|
||||
|
||||
model PL24PartNumber {
|
||||
id String @id @default(cuid())
|
||||
partId String
|
||||
number String @db.VarChar(50)
|
||||
numberClean String? @db.VarChar(50)
|
||||
numberType String @default("ALTERNATE")
|
||||
brand String?
|
||||
priority Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
part PL24Part @relation(fields: [partId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([partId, number])
|
||||
@@index([partId])
|
||||
@@index([number])
|
||||
@@index([numberClean])
|
||||
@@map("pl24_part_numbers")
|
||||
}
|
||||
|
||||
model PL24VehiclePart {
|
||||
id String @id @default(cuid())
|
||||
vehicleId String
|
||||
partId String
|
||||
groupId String?
|
||||
quantity Float @default(1)
|
||||
position String?
|
||||
notes String? @db.Text
|
||||
dateFrom DateTime?
|
||||
dateTo DateTime?
|
||||
conditions Json?
|
||||
createdAt DateTime @default(now())
|
||||
group PL24PartGroup? @relation(fields: [groupId], references: [id])
|
||||
part PL24Part @relation(fields: [partId], references: [id], onDelete: Cascade)
|
||||
vehicle PL24Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([vehicleId, partId, groupId])
|
||||
@@index([vehicleId])
|
||||
@@index([partId])
|
||||
@@index([groupId])
|
||||
@@map("pl24_vehicle_parts")
|
||||
}
|
||||
|
||||
model PL24SchemaPic {
|
||||
id String @id @default(cuid())
|
||||
imageId String @unique
|
||||
localPath String
|
||||
originalUrl String? @db.Text
|
||||
width Int?
|
||||
height Int?
|
||||
fileSize Int?
|
||||
mimeType String? @db.VarChar(50)
|
||||
hotspots Json?
|
||||
createdAt DateTime @default(now())
|
||||
downloadedAt DateTime?
|
||||
vehicleGroups PL24VehicleGroup[]
|
||||
|
||||
@@index([imageId])
|
||||
@@map("pl24_schema_pics")
|
||||
}
|
||||
|
||||
model PL24PartImage {
|
||||
id String @id @default(cuid())
|
||||
groupId String?
|
||||
imageType String @default("DIAGRAM")
|
||||
originalUrl String @db.Text
|
||||
localPath String?
|
||||
imageId String? @unique
|
||||
width Int?
|
||||
height Int?
|
||||
fileSize Int?
|
||||
isPrimary Boolean @default(false)
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
downloadedAt DateTime?
|
||||
group PL24PartGroup? @relation(fields: [groupId], references: [id])
|
||||
|
||||
@@index([groupId])
|
||||
@@index([imageId])
|
||||
@@map("pl24_part_images")
|
||||
}
|
||||
|
||||
enum Role {
|
||||
USER
|
||||
MODERATOR
|
||||
|
||||
BIN
apps/api/public/images/schemas/00000148.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
apps/api/public/images/schemas/00007221.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
apps/api/public/images/schemas/00009623.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
apps/api/public/images/schemas/00011022.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
apps/api/public/images/schemas/00014526.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
apps/api/public/images/schemas/00014527.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
apps/api/public/images/schemas/00019897.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
apps/api/public/images/schemas/00023413.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
apps/api/public/images/schemas/00028226.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
apps/api/public/images/schemas/00028257.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
apps/api/public/images/schemas/00028297.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
apps/api/public/images/schemas/00028311.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
apps/api/public/images/schemas/00028331.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
apps/api/public/images/schemas/00028410.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
apps/api/public/images/schemas/00028446.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
apps/api/public/images/schemas/00028637.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
apps/api/public/images/schemas/00039131.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
apps/api/public/images/schemas/00039136.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
apps/api/public/images/schemas/00039161.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
apps/api/public/images/schemas/00039170.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
apps/api/public/images/schemas/00039187.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
apps/api/public/images/schemas/00056891.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
apps/api/public/images/schemas/00058004.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
apps/api/public/images/schemas/00058052.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
apps/api/public/images/schemas/00060007.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
apps/api/public/images/schemas/00060826.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
apps/api/public/images/schemas/00061950.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
apps/api/public/images/schemas/00062179.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
apps/api/public/images/schemas/00062261.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
apps/api/public/images/schemas/00062315.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
apps/api/public/images/schemas/00062483.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
apps/api/public/images/schemas/00064790.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
apps/api/public/images/schemas/00068776.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
apps/api/public/images/schemas/00072861.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
apps/api/public/images/schemas/00075213.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
apps/api/public/images/schemas/00078102.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
apps/api/public/images/schemas/00086529.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
apps/api/public/images/schemas/00086577.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
apps/api/public/images/schemas/00086638.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
apps/api/public/images/schemas/00086900.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
apps/api/public/images/schemas/00087169.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
apps/api/public/images/schemas/00089580.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
apps/api/public/images/schemas/00091192.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
apps/api/public/images/schemas/00093534.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
apps/api/public/images/schemas/00094130.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
apps/api/public/images/schemas/00094553.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
apps/api/public/images/schemas/00096002.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
apps/api/public/images/schemas/121409150.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
apps/api/public/images/schemas/158100100.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
apps/api/public/images/schemas/158105050.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
apps/api/public/images/schemas/158422400.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
apps/api/public/images/schemas/166103000.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
apps/api/public/images/schemas/166615150.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
apps/api/public/images/schemas/167321550.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
apps/api/public/images/schemas/194103350.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
apps/api/public/images/schemas/194109020.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
apps/api/public/images/schemas/194109520.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
apps/api/public/images/schemas/194300500.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
apps/api/public/images/schemas/194419220.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
apps/api/public/images/schemas/194419350.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
apps/api/public/images/schemas/194511100.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
apps/api/public/images/schemas/194601100.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
apps/api/public/images/schemas/194611220.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
apps/api/public/images/schemas/194611300.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
apps/api/public/images/schemas/194611700.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
apps/api/public/images/schemas/194612100.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
apps/api/public/images/schemas/194614300.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
apps/api/public/images/schemas/194615600.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
apps/api/public/images/schemas/201321500.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
apps/api/public/images/schemas/201325500.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
apps/api/public/images/schemas/203300800.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
apps/api/public/images/schemas/203323700.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
apps/api/public/images/schemas/203419200.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
apps/api/public/images/schemas/203422450.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
apps/api/public/images/schemas/203501100.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
apps/api/public/images/schemas/208321750.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
apps/api/public/images/schemas/220323500.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
apps/api/public/images/schemas/231103410.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
apps/api/public/images/schemas/231419350.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
apps/api/public/images/schemas/231422550.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
apps/api/public/images/schemas/240407100.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
apps/api/public/images/schemas/240411100.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
apps/api/public/images/schemas/240419200.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
apps/api/public/images/schemas/266409500.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
apps/api/public/images/schemas/266411000.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
apps/api/public/images/schemas/266601510.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
apps/api/public/images/schemas/405407280.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
apps/api/public/images/schemas/405422400.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
apps/api/public/images/schemas/405611100.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
apps/api/public/images/schemas/420109000.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
apps/api/public/images/schemas/429260010.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
apps/api/public/images/schemas/460100980.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
apps/api/public/images/schemas/515906100.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
apps/api/public/images/schemas/587300230.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
apps/api/public/images/schemas/596300150.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
apps/api/public/images/schemas/597103028.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
apps/api/public/images/schemas/649109800.png
Normal file
|
After Width: | Height: | Size: 64 KiB |