docs: update INDEX.md + add catalog module, Ford/PSA legacy catalog, shared vehicles

- CatalogModule: VIN-less PL24 catalog browser (brands, models, categories, parts)
  - Supports P5 Modern (REST) and P4 Legacy (Ford, PSA) catalog architectures
  - Ford variant selector (model-year/engine/gearbox), PSA variant selector (body/engine/gearbox)
  - New API endpoints: ford-config, psa-bodies, psa-engines, psa-gearboxes, brands/:name/catalogs
- Shared vehicles: vehicles table decoupled from users via userVehicles junction table
- PL24 Ford Legacy service: comprehensive HTML-scraping for Ford/PSA/Hyundai/Kia/Nissan/Opel/Volvo
- PL24 types and service updated for P4 Legacy brand support
- Categories/parts service updated for dual FK (vehicleId + catalogVehicleId) pattern
- Catalog browser frontend routes and components
- docs/INDEX.md: updated with all new endpoints, components, hooks, routes (2026-03-02)
- docs/pl24-catalog/: per-brand catalog exploration docs
- scripts/migration-shared-vehicles.sql, pl24-catalog-explorer.js, posthog-dashboards.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sase Dev
2026-03-02 00:31:15 +00:00
parent f2189a014b
commit 72c0de65de
90 changed files with 12043 additions and 419 deletions

View File

@@ -1,223 +0,0 @@
/**
* EMEX VIN Scraper - Playwright Benchmark
* Same flow as puppeteer-based emex-vin-scraper.js but using Playwright
*/
const { chromium } = require('playwright');
const VIN = process.argv[2] || 'NM0GXXTTPGAG07617';
const CONFIG = {
baseUrl: 'https://emexdwc.ae',
timeout: 60000,
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
catalogMap: {
'WBA': 'BMW202501', 'WBS': 'BMW202501', 'WBY': 'BMW202501',
'WDB': 'MB201810', 'WDD': 'MB201810', 'WDC': 'MB201810', 'WDF': 'MB201810',
'WAU': 'AU1587', 'WVW': 'VW1587', 'WVG': 'VW1587',
'VF1': 'RENAULT201910', 'VF7': 'CPSA01', 'VF3': 'CPSA01',
'ZFA': 'CFIAT84', 'ZAR': 'RFIAT84',
'WF0': 'FORD202201', 'NM0': 'FORD202201',
'JTD': 'TOYOTA00', 'JTE': 'TOYOTA00',
'WP0': 'PO799', 'WP1': 'PO799',
},
brandMap: {
'BMW202501': 'BMW', 'MB201810': 'Mercedes-Benz', 'AU1587': 'Audi',
'VW1587': 'Volkswagen', 'RENAULT201910': 'Renault', 'CPSA01': 'Peugeot',
'CFIAT84': 'Fiat', 'RFIAT84': 'Alfa Romeo', 'FORD202201': 'Ford',
'TOYOTA00': 'Toyota', 'PO799': 'Porsche',
}
};
function getCatalogCode(vin) {
return CONFIG.catalogMap[vin.substring(0, 3)] || null;
}
function getBrand(code) {
return CONFIG.brandMap[code] || code;
}
(async () => {
const totalStart = performance.now();
const timings = {};
console.log('=' .repeat(70));
console.log('EMEX VIN SCRAPER - PLAYWRIGHT BENCHMARK');
console.log('=' .repeat(70));
console.log(`VIN: ${VIN}`);
const catalogCode = getCatalogCode(VIN);
console.log(`Catalog: ${catalogCode}`);
console.log('=' .repeat(70));
// ── Launch browser ──
let t = performance.now();
const browser = await chromium.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
]
});
const context = await browser.newContext({
userAgent: CONFIG.userAgent,
viewport: { width: 1920, height: 1080 },
});
const page = await context.newPage();
timings.browserLaunch = performance.now() - t;
console.log(`[${timings.browserLaunch.toFixed(0)}ms] Browser launched`);
// ── Step 1: Establish session ──
t = performance.now();
await page.goto(CONFIG.baseUrl, { waitUntil: 'networkidle', timeout: CONFIG.timeout });
timings.session = performance.now() - t;
const cookies = await context.cookies();
const sessionCookie = cookies.find(c => c.name === 'ASP.NET_SessionId')?.value || '';
console.log(`[${timings.session.toFixed(0)}ms] Session: ${sessionCookie ? 'established' : 'none'}`);
// ── Step 2: VIN URL search ──
t = performance.now();
const vinUrl = `${CONFIG.baseUrl}/Vehicles.aspx?ft=findByVIN&c=&ssd=&vin=${VIN}`;
console.log(`\nNavigating to: ${vinUrl}`);
await page.goto(vinUrl, { waitUntil: 'networkidle', timeout: CONFIG.timeout });
await page.waitForTimeout(1500); // wait for dynamic content
timings.vinSearch = performance.now() - t;
// Extract vehicle links
const vehicleLinks = await page.evaluate(() => {
const results = [];
const links = document.querySelectorAll('a[href*="Vehicle.aspx"], a[href*="QuickGroups.aspx"]');
links.forEach(link => {
const href = link.href;
const name = link.textContent.trim();
if (name && !results.some(r => r.name === name)) {
const cMatch = href.match(/[?&]c=([^&]+)/);
const ssdMatch = href.match(/[?&]ssd=([^&]+)/);
results.push({
name,
href,
catalogCode: cMatch ? cMatch[1] : '',
ssd: ssdMatch ? decodeURIComponent(ssdMatch[1]) : '',
isQuickGroups: href.includes('QuickGroups.aspx'),
});
}
});
return results;
});
console.log(`[${timings.vinSearch.toFixed(0)}ms] VIN search → ${vehicleLinks.length} vehicle(s) found`);
if (vehicleLinks.length > 0) {
const v = vehicleLinks[0];
console.log(` Vehicle: ${v.name}`);
}
// ── Step 3: Fetch category tree ──
const qgLink = vehicleLinks.find(l => l.isQuickGroups);
let quickGroupsUrl = qgLink?.href || null;
if (!quickGroupsUrl && vehicleLinks.length > 0) {
const first = vehicleLinks[0];
if (first.ssd) {
const vidMatch = first.href.match(/[?&]vid=([^&]+)/);
const vid = vidMatch ? vidMatch[1] : '0';
quickGroupsUrl = `${CONFIG.baseUrl}/QuickGroups.aspx?c=${first.catalogCode || catalogCode}&vid=${vid}&ssd=${encodeURIComponent(first.ssd)}`;
}
}
let categories = [];
if (quickGroupsUrl) {
t = performance.now();
await page.goto(quickGroupsUrl, { waitUntil: 'networkidle', timeout: CONFIG.timeout });
await page.waitForTimeout(1500);
categories = await page.evaluate(() => {
const cats = [];
const links = document.querySelectorAll('a[href*="QuickDetails"], a[href*="gid="]');
links.forEach(link => {
const gidMatch = link.href.match(/gid=(\d+)/);
if (gidMatch) {
cats.push({ gid: gidMatch[1], name: link.textContent.trim(), url: link.href });
}
});
return cats;
});
timings.categories = performance.now() - t;
console.log(`[${timings.categories.toFixed(0)}ms] Categories → ${categories.length} found`);
}
// ── Step 4: Fetch first category parts ──
let parts = [];
let schemaImageUrl = null;
if (categories.length > 0) {
const firstCatUrl = categories[0].url;
t = performance.now();
console.log(`\nFetching parts from: ${categories[0].name}`);
await page.goto(firstCatUrl, { waitUntil: 'networkidle', timeout: CONFIG.timeout });
await page.waitForTimeout(1500);
// Check if we landed on Unit.aspx (redirect for BOM leaf nodes)
const currentUrl = page.url();
if (currentUrl.includes('QuickDetails.aspx')) {
// Look for Unit.aspx links
const unitLink = await page.evaluate(() => {
const link = document.querySelector('a[href*="Unit.aspx"]');
return link ? link.href : null;
});
if (unitLink) {
console.log(' Following Unit.aspx link...');
await page.goto(unitLink, { waitUntil: 'networkidle', timeout: CONFIG.timeout });
await page.waitForTimeout(1500);
}
}
// Extract parts from the page
const partsData = await page.evaluate(() => {
const result = { parts: [], schemaImageUrl: null };
// Schema image
const img = document.querySelector('img[src*="GetImage"], img[src*="schema"], img.partImage, #imgSchema');
if (img) result.schemaImageUrl = img.src;
// Parts table
const rows = document.querySelectorAll('table tr, .partRow, [class*="part"]');
rows.forEach(row => {
const cells = row.querySelectorAll('td');
if (cells.length >= 2) {
const name = cells[0]?.textContent?.trim() || '';
const partNumber = cells[1]?.textContent?.trim() || '';
if (name && partNumber) {
result.parts.push({ name, partNumber });
}
}
});
return result;
});
parts = partsData.parts;
schemaImageUrl = partsData.schemaImageUrl;
timings.parts = performance.now() - t;
console.log(`[${timings.parts.toFixed(0)}ms] Parts → ${parts.length} found, schema: ${schemaImageUrl ? 'yes' : 'no'}`);
}
// ── Cleanup ──
await browser.close();
// ── Summary ──
const totalTime = performance.now() - totalStart;
console.log('\n' + '=' .repeat(70));
console.log('PLAYWRIGHT BENCHMARK RESULTS');
console.log('=' .repeat(70));
console.log(`Browser launch: ${timings.browserLaunch?.toFixed(0) || '-'}ms`);
console.log(`Session establish: ${timings.session?.toFixed(0) || '-'}ms`);
console.log(`VIN search: ${timings.vinSearch?.toFixed(0) || '-'}ms`);
console.log(`Categories: ${timings.categories?.toFixed(0) || '-'}ms`);
console.log(`Parts (1st cat): ${timings.parts?.toFixed(0) || '-'}ms`);
console.log('-'.repeat(70));
console.log(`TOTAL: ${totalTime.toFixed(0)}ms (${(totalTime / 1000).toFixed(1)}s)`);
console.log('=' .repeat(70));
console.log(`Vehicle: ${getBrand(catalogCode)} - ${vehicleLinks[0]?.name || 'N/A'}`);
console.log(`Categories: ${categories.length}`);
console.log(`Parts (sample): ${parts.length}`);
})();

253
CLAUDE.md
View File

@@ -16,7 +16,10 @@
| **Styling** | Tailwind CSS 4, shadcn/ui (Radix primitives) | | **Styling** | Tailwind CSS 4, shadcn/ui (Radix primitives) |
| **State** | Zustand 5 | | **State** | Zustand 5 |
| **Payments** | Iyzico (card) + EFT (bank transfer) | | **Payments** | Iyzico (card) + EFT (bank transfer) |
| **Email** | Postal (transactional) |
| **Storage** | MinIO (S3-compatible) | | **Storage** | MinIO (S3-compatible) |
| **Analytics** | PostHog (product analytics) |
| **Observability** | OpenTelemetry (API) + Grafana Faro (frontend) |
| **Testing** | Vitest 3, Playwright 1.50 | | **Testing** | Vitest 3, Playwright 1.50 |
| **Linting** | Biome (2-space indent, double quotes, semicolons, trailing commas) | | **Linting** | Biome (2-space indent, double quotes, semicolons, trailing commas) |
| **CI/CD** | GitHub Actions → SSH deploy → PM2 | | **CI/CD** | GitHub Actions → SSH deploy → PM2 |
@@ -31,27 +34,28 @@ ss/
│ │ ├── main.ts # Bootstrap (Helmet, CORS, rate limiting) │ │ ├── main.ts # Bootstrap (Helmet, CORS, rate limiting)
│ │ ├── app.module.ts # Root module (global guards/interceptors/filters) │ │ ├── app.module.ts # Root module (global guards/interceptors/filters)
│ │ ├── worker.ts # BullMQ worker process │ │ ├── worker.ts # BullMQ worker process
│ │ ├── database/schema/ # Drizzle ORM schemas (core.ts, emex.ts, pl24.ts, relations.ts) │ │ ├── database/schema/ # Drizzle ORM schemas (core.ts, emex.ts, pl24.ts, parts-catalogs.ts, relations.ts)
│ │ ├── common/ # Guards, interceptors, filters, decorators, pipes, DTOs │ │ ├── common/ # Guards, interceptors, filters, decorators, pipes, DTOs
│ │ ├── integrations/ # corgi/, pl24/, emex/, vin-api/ │ │ ├── integrations/ # corgi/, pl24/, emex/, parts-catalogs/, vin-api/
│ │ └── [modules]/ # auth, users, brands, plans, subscriptions, payments, │ │ └── [modules]/ # auth, users, brands, plans, subscriptions, payments,
│ │ # referrals, vehicles, categories, parts, translations, │ │ # referrals, vehicles, categories, parts, catalog,
│ │ # admin, jobs, email, storage, redis │ │ # translations, analytics, admin, jobs, email, storage, redis,
│ │ # telemetry
│ └── web/ # Vite + React frontend (port 3000) │ └── web/ # Vite + React frontend (port 3000)
│ └── src/ │ └── src/
│ ├── main.tsx # Entry (RouterProvider, QueryClientProvider) │ ├── main.tsx # Entry (RouterProvider, QueryClientProvider, Faro, PostHog)
│ ├── routes/ # TanStack Router file-based routes │ ├── routes/ # TanStack Router file-based routes
│ ├── components/ # admin/, schema/, vehicles/, categories/, payment/, settings/, subscription/ │ ├── components/ # admin/, schema/, vehicles/, categories/, payment/, settings/, subscription/
│ ├── hooks/ # useAuth, useParts, useSchemaInteraction │ ├── hooks/ # useAuth, useParts, useSchemaInteraction
│ ├── stores/ # Zustand: auth.store.ts, schema.store.ts │ ├── stores/ # Zustand: auth.store.ts, schema.store.ts
│ ├── lib/ # api-client, auth-client, i18n, toast, user-settings │ ├── lib/ # api-client, auth-client, i18n, posthog, faro, toast, user-settings, category-icons
│ └── messages/ # tr.json, en.json (i18n) │ └── messages/ # tr.json, en.json (i18n)
├── packages/ ├── packages/
│ ├── shared/ # @sase/shared — types, Zod schemas, constants, utils │ ├── shared/ # @sase/shared — types, Zod schemas, constants, utils
│ ├── config/ # @sase/config — Zod env validation schema │ ├── config/ # @sase/config — Zod env validation schema
│ └── ui/ # @sase/ui — shadcn-based React components │ └── ui/ # @sase/ui — shadcn-based React components
├── docker/ # docker-compose.yml (PostgreSQL, Redis, MinIO) ├── docker/ # docker-compose.yml (PostgreSQL, Redis, MinIO) + nginx configs
├── scripts/ # deploy.sh, test scripts ├── scripts/ # deploy.sh, test/debug scripts
├── docs/ # INDEX.md + detailed docs (00-13) ├── docs/ # INDEX.md + detailed docs (00-13)
└── ecosystem.config.js # PM2 config (api, web, worker) └── ecosystem.config.js # PM2 config (api, web, worker)
``` ```
@@ -93,17 +97,147 @@ pnpm --filter web exec tsr generate
- **Route files:** TanStack Router auto-generates `routeTree.gen.ts` — never edit manually - **Route files:** TanStack Router auto-generates `routeTree.gen.ts` — never edit manually
- **i18n:** Turkish default (`tr.json`), English available (`en.json`). Use `useTranslation()` hook → `t("key")` - **i18n:** Turkish default (`tr.json`), English available (`en.json`). Use `useTranslation()` hook → `t("key")`
## Backend Modules
| Module | Purpose |
|--------|---------|
| **AuthModule** | Better Auth (email/password + Google OAuth) |
| **UsersModule** | Profile CRUD, password change, OAuth connections, account deletion |
| **BrandsModule** | Brand CRUD (cached, admin-managed) |
| **PlansModule** | Pricing plan CRUD (cached, admin-managed) |
| **SubscriptionsModule** | Create, activate, cancel, resume, extend subscriptions |
| **PaymentsModule** | Iyzico card + EFT with receipt upload + admin approval |
| **ReferralsModule** | Referral code generation, tier-based rewards |
| **VehiclesModule** | VIN decode (multi-source fallback), vehicle history, brand access check |
| **CategoriesModule** | Hierarchical category tree, schema pictures |
| **PartsModule** | Parts by category, OEM code search |
| **CatalogModule** | VIN-less catalog browser — PL24 brands, models, category trees, parts |
| **TranslationsModule** | Automotive term translation (Redis → DB → Dictionary fallback) |
| **AnalyticsModule** | OEM code copy tracking, usage analytics |
| **AdminModule** | Dashboard stats, user management, payment approval |
| **EmailModule** | Postal transactional emails (welcome, payment confirmation, password reset) |
| **StorageModule** | S3/MinIO file upload/download |
| **RedisModule** | Key-value cache operations |
| **JobsModule** | BullMQ queues + processors + prefetch worker |
| **TelemetryModule** | OpenTelemetry SDK (tracing, metrics) |
## Architecture Patterns ## Architecture Patterns
- **Global guards order:** ThrottlerGuard → AuthGuard → RolesGuard - **Global guards order:** ThrottlerGuard → AuthGuard → RolesGuard
- **Global interceptors:** TransformInterceptor → LoggingInterceptor → TimeoutInterceptor (30s) - **Global interceptors:** TransformInterceptor → LoggingInterceptor → TimeoutInterceptor (30s)
- **Global filters:** HttpExceptionFilter, DrizzleExceptionFilter (unique constraint → 409) - **Global filters:** HttpExceptionFilter, DrizzleExceptionFilter (unique constraint → 409)
- **VIN decode chain:** Corgi (offline WMI) → PL24 API → PartsCatalogs API → EMEX scraper → NHTSA VIN API
- **Category fetch chain:** DB cache → PL24 → PartsCatalogs → EMEX (lazy, source-based in `getCategoryTree`)
- **Caching:** Redis for sessions (5min), brands/plans (30min HTTP cache), translations, category trees
- **Job queues (BullMQ):** EMEX_SCRAPE (on-demand), CATALOG_PREFETCH (on-demand, post-VIN-decode, depth-limited), SUBSCRIPTION_EXPIRY (daily 3AM), QUERY_CLEANUP (weekly Sun 4AM)
- **Vite proxy:** `/api` requests → `http://localhost:4000` in dev - **Vite proxy:** `/api` requests → `http://localhost:4000` in dev
### VIN Decode Fallback Chain
Corgi (offline WMI) → **PartsCatalogs API** → PL24 API → EMEX scraper → NHTSA VIN API
> Note: PartsCatalogs was added between Corgi and PL24 as it has broader VIN coverage. If multiple car matches return, the frontend prompts the user to select.
### Category Fetch Chain (VIN-based)
DB cache → PL24 → PartsCatalogs → EMEX (lazy, source-based in `getCategoryTree`)
### Catalog Browse Flow (VIN-less)
1. `GET /catalog/brands` → check user subscription access per brand
2. `GET /catalog/brands/:name/models` → PL24 `fetchVehicleList()` → stored in `catalogVehicles` table
3. `GET /catalog/vehicles/:id/categories` → PL24 `fetchMainGroups()` → stored in `categories` with `catalogVehicleId`
4. `GET /catalog/vehicles/:id/categories/:categoryId` → PL24 `fetchSubGroupsByPath()` / `fetchPartsByPath()` → stored lazily
### PL24 Catalog Architectures
- **P5_MODERN** (REST JSON API): VW Group, BMW, Mini, Mercedes, Porsche, Renault, Dacia, Alpine, Jaguar, Land Rover, Toyota, Lexus, MAN, Mitsubishi, Suzuki, etc.
- **LEGACY_PSA** (HTML scraping): Citroën, Peugeot
- **LEGACY_FORD** (HTML scraping): Ford passenger (wf0_parts) + commercial (fordt_parts)
- **LEGACY_HYUNDAI_KIA** (HTML scraping): Hyundai, Kia
- **LEGACY_NISSAN** (HTML scraping): Nissan, Infiniti
- **LEGACY_OPEL** (HTML scraping): Opel, Vauxhall
- **LEGACY_VOLVO** (HTML scraping): Volvo, Polestar
Our PL24 account (tr-903645) supports **VAG group only** for VIN-less catalog. Other brands may return errors on model listing. All P4 Legacy VIN decodes route through `PL24FordLegacyService.decodeVinForService(vin, serviceName)`.
### Caching Strategy
- Redis: VIN decode results (24h), category trees (2h for catalog browser), parts fetches (1h), translations
- HTTP Cache: brands, plans (30min `Cache-Control`)
- Sessions: Better Auth (5min Redis)
### Job Queues (BullMQ)
| Queue | Trigger | Schedule |
|-------|---------|----------|
| `EMEX_SCRAPE` | On-demand (VIN decode) | — |
| `CATALOG_PREFETCH` | After VIN decode | — (depth-limited, rate-limited, cooldown-guarded) |
| `SUBSCRIPTION_EXPIRY` | Cron | Daily 3:00 AM |
| `QUERY_CLEANUP` | Cron | Weekly Sunday 4:00 AM |
### Subscription & Access Control
- Plans have `brandCount` field: `0` = unlimited access, `N` = limited to N brands
- Brand access tracked in `userBrands` junction table (userId + subscriptionId + brandId)
- Full plan (brandCount=0) auto-adds all active brands on activation
- `BrandAccessGuard` (per-route) verifies user's subscription includes the requested brand
## Database Schema Summary
**Schema files:** `apps/api/src/database/schema/`
- `core.ts` — Main application tables
- `emex.ts` — EMEX scraper cache tables
- `pl24.ts` — PL24 catalog cache tables
- `parts-catalogs.ts` — PartsCatalogs API cache tables
- `relations.ts` — Drizzle ORM relationships
**Key tables in `core.ts`:**
- `users`, `sessions`, `accounts`, `verifications` — Better Auth managed
- `brands`, `plans` — Catalog of available brands/plans (admin-managed)
- `userSubscriptions` — status: pending/active/trial/cancelled/expired
- `userBrands` — junction table controlling brand access per subscription
- `payments` — Iyzico or EFT, status tracking
- `vehicles` — one per unique VIN, shared across users via `userVehicles`
- `userVehicles` — junction (userId + vehicleId unique), tracks lastAccessedAt
- `categories` — parent-child hierarchy; has both `vehicleId` (VIN-based) and `catalogVehicleId` (VIN-less) FKs (nullable for the other mode)
- `parts` — OEM code, quantity, hotspot index; same dual FK pattern as categories
- `schemaPics` — exploded view images + hotspots JSONB, linked to categories
- `catalogVehicles` — VIN-less catalog: one record per PL24 service vehicle (unique on source + serviceVehicleId)
- `queryLogs` — VIN decode audit trail
- `oemCodeCopies` — OEM code copy events (analytics)
- `referrals`, `passwordResetTokens`, `emexCategoryTranslations`
## Integrations
| Integration | Type | Path | Notes |
|-------------|------|------|-------|
| **Corgi** | Offline DB | `integrations/corgi/` | WMI database for brand ID |
| **PL24** | REST API + HTML scraper | `integrations/pl24/` | Multi-brand catalog; P5 (REST) + P4 Legacy (HTML). Services: `pl24.service.ts`, `pl24-ford-legacy.service.ts` |
| **PartsCatalogs** | REST API + Playwright JWT | `integrations/parts-catalogs/` | Broad VIN coverage; JWT captured via Playwright from partner sites; IP-bound via DataImpulse proxy |
| **EMEX** | Browser scraper | `integrations/emex/` | Playwright-based (emexdwc.ae), async via BullMQ |
| **VIN-API** | REST API | `integrations/vin-api/` | NHTSA VIN decoder (last-resort fallback) |
## Frontend Routes
**Public:** `/`, `/pricing`, `/about`, `/contact`, `/blog`, `/demo`, `/privacy`, `/terms`, `/kvkk`
**Auth (layout `_auth.tsx`):** `/login`, `/register`, `/forgot-password`, `/reset-password`
**Dashboard (protected, layout `dashboard.tsx`):**
- `/dashboard` — Home
- `/dashboard/search` — VIN decode input
- `/dashboard/history` — Past VIN searches
- `/dashboard/subscription` — Plan/brand selection
- `/dashboard/subscription/pay` — Payment (Iyzico or EFT)
- `/dashboard/billing` — Payment history
- `/dashboard/settings` — Profile, Security, Connections, Referral tabs
- `/dashboard/vehicles/$id` — Vehicle details
- `/dashboard/vehicles/$id/categories/$categoryId` — Interactive schema + parts
**Catalog Browser (VIN-less, protected):**
- `/dashboard/catalog` — Brand grid with access flags
- `/dashboard/catalog/$brandName` — Model list (from PL24)
- `/dashboard/catalog/$brandName/$modelId` — Category tree/grid view
- `/dashboard/catalog/$brandName/$modelId/categories/$categoryId` — Sub-categories or schema+parts
**Admin (role-based):**
- `/dashboard/admin` — Stats + charts
- `/dashboard/admin/users` — User management
- `/dashboard/admin/payments` — EFT approval workflow
- `/dashboard/admin/referrals` — Referral tracking
- `/dashboard/admin/analytics` — Daily query stats
- `/dashboard/admin/copy-logs` — OEM code copy tracking
## Auth & Test Credentials ## Auth & Test Credentials
- **Admin:** `admin@sase.tr` / `Sase2026` - **Admin:** `admin@sase.tr` / `Sase2026`
@@ -115,12 +249,105 @@ pnpm --filter web exec tsr generate
**Required:** `DATABASE_URL`, `REDIS_PASSWORD`, `BETTER_AUTH_SECRET` (min 32 chars), `BETTER_AUTH_URL`, `MINIO_ENDPOINT`, `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_PUBLIC_URL`, `CORS_ORIGIN` **Required:** `DATABASE_URL`, `REDIS_PASSWORD`, `BETTER_AUTH_SECRET` (min 32 chars), `BETTER_AUTH_URL`, `MINIO_ENDPOINT`, `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_PUBLIC_URL`, `CORS_ORIGIN`
**Optional:** `PORT` (4000), `REDIS_HOST` (127.0.0.1), `REDIS_PORT` (6379), `GOOGLE_CLIENT_ID/SECRET`, `IYZICO_API_KEY/SECRET_KEY/BASE_URL`, `PL24_BASE_URL/COMPANY_CODE/USERNAME/PASSWORD`, `EMEX_USERNAME/PASSWORD`, `ML_PREDICTION_ENABLED` **Optional (grouped):**
- `PORT` (4000), `REDIS_HOST` (127.0.0.1), `REDIS_PORT` (6379), `MINIO_BUCKET_NAME` (sase-schemas), `MINIO_USE_SSL` (false)
- `GOOGLE_CLIENT_ID/SECRET` — Google OAuth
- `IYZICO_API_KEY/SECRET_KEY/BASE_URL` — Payment processing
- `PL24_BASE_URL/COMPANY_CODE/USERNAME/PASSWORD` — PL24 catalog API
- `EMEX_USERNAME/PASSWORD` — EMEX scraper
- `PCAT_USE_PROXY` (true), `PCAT_PROXY_HOST` (gw.dataimpulse.com), `PCAT_PROXY_USER/PASS` — PartsCatalogs proxy
- `POSTAL_API_URL/API_KEY`, `POSTAL_FROM_ADDRESS` (noreply@sase.tr), `POSTAL_FROM_NAME` (Sase.tr) — Email
- `OTEL_ENABLED` (false), `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_SERVICE_NAME` (sase-api), `OTEL_TRACE_SAMPLE_RATE` (1.0) — OpenTelemetry
- `ML_PREDICTION_ENABLED` (false)
Full schema: `packages/config/src/index.ts` Full schema: `packages/config/src/index.ts`
## Common Gotchas
- **Frontend is Vite + TanStack Router** — NOT Next.js
- **Categories & Parts tables have dual FKs:** `vehicleId` (VIN-based, nullable) and `catalogVehicleId` (VIN-less, nullable) — always check which context you're in
- **PartsCatalogs JWT is IP-bound** via DataImpulse proxy; the auth service manages a warm pool of JWTs using Playwright
- **P4 Legacy brands have no REST API** — Ford, PSA, Hyundai/Kia, Nissan, Opel, Volvo all use HTML scraping through `PL24FordLegacyService`
- **`catalogVehicles` unique key** is `(source, serviceVehicleId)` — not by VIN (these vehicles may not have VINs)
- **`routeTree.gen.ts`** is auto-generated by TanStack Router — never edit manually
- **DrizzleExceptionFilter** catches unique constraint violations → 409 Conflict
- **File uploads:** PNG/JPG/PDF only, max 5MB (middleware in `main.ts`)
- **Env validation** uses Zod from `@sase/config` — app won't start if env vars invalid
- **Playwright (EMEX/PartsCatalogs):** `waitUntil: 'networkidle'` (not `networkidle2`); `page.context().cookies()` (not `page.cookies()`)
- **VIN decode may return candidates** if PartsCatalogs finds multiple matches — frontend shows selection modal
## ast-grep — Structural Code Search & Refactoring
ast-grep (`sg`) does AST-aware pattern matching — finds code by structure, not text. Unlike `grep`, it understands syntax so `foo( bar )` and `foo(bar)` both match the pattern `foo($X)`.
**Install:** `npm i -g @ast-grep/cli` (already installed globally)
### Pattern syntax
| Syntax | Meaning |
|--------|---------|
| `$VAR` | Matches any **single** AST node (expression, identifier, etc.) |
| `$$$ARGS` | Matches **zero or more** nodes (variadic — use for argument lists, statements) |
| Literal code | Matches exact syntax structure |
### Common commands
```bash
# Search by pattern in TypeScript files
ast-grep -p 'console.log($$$)' -l ts apps/
# Search and preview rewrite (no changes yet)
ast-grep -p '$A && $A()' --rewrite '$A?.()' -l ts apps/
# Interactive rewrite — confirm each change
ast-grep -p '$A && $A()' --rewrite '$A?.()' --interactive -l ts apps/
# Apply all rewrites without confirmation
ast-grep -p '$A && $A()' --rewrite '$A?.()' --update-all -l ts apps/
# Output matches as JSON (useful for scripting)
ast-grep -p 'useQuery($$$)' -l tsx --json apps/web/src/
# Show surrounding context lines
ast-grep -p 'db.select()' -l ts -C 3 apps/api/src/
# Limit to specific file globs
ast-grep -p '@Public()' -l ts --globs 'apps/api/src/**/*.controller.ts' .
```
### Language flags for this project
| Flag | Use for |
|------|---------|
| `-l ts` | API services, guards, modules, DTOs |
| `-l tsx` | React components, route files |
| `-l json` | i18n message files |
### Useful patterns for this codebase
```bash
# Find all @Public() decorated endpoints
ast-grep -p '@Public()' -l ts apps/api/src/
# Find all useQuery calls (TanStack Query)
ast-grep -p 'useQuery({$$$})' -l tsx apps/web/src/
# Find Drizzle inserts
ast-grep -p 'db.insert($TABLE).values($$$)' -l ts apps/api/src/
# Find all Redis cache sets
ast-grep -p 'this.redis.set($$$)' -l ts apps/api/src/
# Find t() translation calls missing a key
ast-grep -p 't($KEY)' -l tsx apps/web/src/
# Find all BullMQ queue.add() calls
ast-grep -p '$QUEUE.add($$$)' -l ts apps/api/src/jobs/
```
## Documentation ## Documentation
- **Project index:** `docs/INDEX.md` (comprehensive — routes, API endpoints, DB schema, components) - **Project index:** `docs/INDEX.md` (comprehensive — routes, API endpoints, DB schema, components)
- **Marketing context:** `.claude/product-marketing-context.md` - **Marketing context:** `.claude/product-marketing-context.md`
- **Detailed docs:** `docs/00-overview.md` through `docs/13-analytics-posthog.md` - **Detailed docs:** `docs/00-overview.md` through `docs/13-analytics-posthog.md`
- **Memory:** `.claude/projects/-home-s-ss/memory/MEMORY.md`

View File

@@ -24,6 +24,7 @@ import { EmexModule } from "./integrations/emex/emex.module";
import { TranslationsModule } from "./translations/translations.module"; import { TranslationsModule } from "./translations/translations.module";
import { AdminModule } from "./admin/admin.module"; import { AdminModule } from "./admin/admin.module";
import { AnalyticsModule } from "./analytics/analytics.module"; import { AnalyticsModule } from "./analytics/analytics.module";
import { CatalogModule } from "./catalog/catalog.module";
import { HealthController } from "./health.controller"; import { HealthController } from "./health.controller";
import { AuthGuard } from "./common/guards/auth.guard"; import { AuthGuard } from "./common/guards/auth.guard";
import { RolesGuard } from "./common/guards/roles.guard"; import { RolesGuard } from "./common/guards/roles.guard";
@@ -70,6 +71,7 @@ import { HttpExceptionFilter } from "./common/filters/http-exception.filter";
TranslationsModule, TranslationsModule,
AdminModule, AdminModule,
AnalyticsModule, AnalyticsModule,
CatalogModule,
], ],
controllers: [HealthController], controllers: [HealthController],
providers: [ providers: [

View File

@@ -0,0 +1,92 @@
import { Controller, Get, Param, Post, Query } from "@nestjs/common";
import { CurrentUser } from "../common/decorators/current-user.decorator";
import { Roles } from "../common/decorators/roles.decorator";
import { CatalogService } from "./catalog.service";
@Controller("catalog")
export class CatalogController {
constructor(private catalogService: CatalogService) {}
@Get("brands")
getBrands(@CurrentUser() user: { id: string }) {
return this.catalogService.getBrands(user.id);
}
@Get("brands/:brandName/catalogs")
getCatalogs(@Param("brandName") brandName: string, @CurrentUser() user: { id: string }) {
return this.catalogService.getCatalogs(brandName, user.id);
}
@Get("brands/:brandName/models")
getModels(
@Param("brandName") brandName: string,
@Query("service") service: string | undefined,
@CurrentUser() user: { id: string },
) {
return this.catalogService.getModels(brandName, user.id, service);
}
@Get("vehicles/:id")
getVehicle(@Param("id") id: string, @CurrentUser() user: { id: string }) {
return this.catalogService.getVehicle(id, user.id);
}
@Get("vehicles/:id/ford-config")
getFordModelConfig(@Param("id") id: string, @CurrentUser() user: { id: string }) {
return this.catalogService.getFordModelConfig(id, user.id);
}
@Get("vehicles/:id/psa-bodies")
getPsaBodies(@Param("id") id: string, @CurrentUser() user: { id: string }) {
return this.catalogService.getPsaBodies(id, user.id);
}
@Get("vehicles/:id/psa-engines")
getPsaEngines(
@Param("id") id: string,
@Query("body") body: string,
@CurrentUser() user: { id: string },
) {
return this.catalogService.getPsaEngines(id, body, user.id);
}
@Get("vehicles/:id/psa-gearboxes")
getPsaGearboxes(
@Param("id") id: string,
@Query("body") body: string,
@Query("engine") engine: string,
@CurrentUser() user: { id: string },
) {
return this.catalogService.getPsaGearboxes(id, body, engine, user.id);
}
@Get("vehicles/:id/categories")
getCategoryTree(
@Param("id") id: string,
@Query("body") body: string | undefined,
@Query("engine") engine: string | undefined,
@Query("gearbox") gearbox: string | undefined,
@CurrentUser() user: { id: string },
) {
return this.catalogService.getCategoryTree(id, user.id, body, engine, gearbox);
}
@Get("vehicles/:id/categories/:categoryId")
getCategoryWithParts(
@Param("id") id: string,
@Param("categoryId") categoryId: string,
@Query("body") body: string | undefined,
@Query("engine") engine: string | undefined,
@Query("gearbox") gearbox: string | undefined,
@CurrentUser() user: { id: string },
) {
return this.catalogService.getCategoryWithParts(id, categoryId, user.id, body, engine, gearbox);
}
/** Admin: explore a PL24 service catalog structure for discovery */
@Post("explore/:serviceName")
@Roles("admin")
exploreService(@Param("serviceName") serviceName: string) {
return this.catalogService.exploreService(serviceName);
}
}

View File

@@ -0,0 +1,14 @@
import { Module } from "@nestjs/common";
import { CatalogController } from "./catalog.controller";
import { CatalogService } from "./catalog.service";
import { PL24Module } from "../integrations/pl24/pl24.module";
import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
import { StorageModule } from "../storage/storage.module";
@Module({
imports: [PL24Module, SubscriptionsModule, StorageModule],
controllers: [CatalogController],
providers: [CatalogService],
exports: [CatalogService],
})
export class CatalogModule {}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
export class ExploreServiceDto {
serviceName!: string;
}

View File

@@ -22,7 +22,10 @@ function createService(db: any) {
fetchGroups: vi.fn().mockResolvedValue([]), fetchGroups: vi.fn().mockResolvedValue([]),
fetchParts: vi.fn().mockResolvedValue(null), fetchParts: vi.fn().mockResolvedValue(null),
}; };
const service = new CategoriesService(db as any, redis as any, pl24Service as any, emexService as any, partsCatalogsService as any, storage as any); const pl24FordLegacyService = {
fetchCategoriesForPsaVin: vi.fn().mockResolvedValue([]),
};
const service = new CategoriesService(db as any, redis as any, pl24Service as any, emexService as any, partsCatalogsService as any, storage as any, pl24FordLegacyService as any);
return { service, db, redis, pl24Service }; return { service, db, redis, pl24Service };
} }

View File

@@ -1,11 +1,13 @@
import { Inject, Injectable, Logger, NotFoundException } from "@nestjs/common"; import { Inject, Injectable, Logger, NotFoundException } from "@nestjs/common";
import { eq, inArray, sql } from "drizzle-orm"; import { eq, inArray, isNull, sql } from "drizzle-orm";
import { DATABASE, Database } from "../database/database.provider"; import { DATABASE, Database } from "../database/database.provider";
import { categories, vehicles, schemaPics, parts } from "../database/schema/core"; import { categories, vehicles, schemaPics, parts } from "../database/schema/core";
import { RedisService } from "../redis/redis.service"; import { RedisService } from "../redis/redis.service";
import { PL24Service } from "../integrations/pl24/pl24.service"; import { PL24Service } from "../integrations/pl24/pl24.service";
import { PL24FordLegacyService } from "../integrations/pl24/pl24-ford-legacy.service";
import { EmexService } from "../integrations/emex/emex.service"; import { EmexService } from "../integrations/emex/emex.service";
import { PartsCatalogsService } from "../integrations/parts-catalogs/parts-catalogs.service"; import { PartsCatalogsService } from "../integrations/parts-catalogs/parts-catalogs.service";
import type { PcatGroup } from "../integrations/parts-catalogs/parts-catalogs.types";
import { StorageService } from "../storage/storage.service"; import { StorageService } from "../storage/storage.service";
@Injectable() @Injectable()
@@ -19,6 +21,7 @@ export class CategoriesService {
private emexService: EmexService, private emexService: EmexService,
private partsCatalogsService: PartsCatalogsService, private partsCatalogsService: PartsCatalogsService,
private storage: StorageService, private storage: StorageService,
private pl24FordLegacyService: PL24FordLegacyService,
) {} ) {}
async getCategoryTree(vehicleId: string) { async getCategoryTree(vehicleId: string) {
@@ -65,6 +68,7 @@ export class CategoriesService {
const insertData = uniquePl24.map((c) => ({ const insertData = uniquePl24.map((c) => ({
vehicleId, vehicleId,
catalogVehicleId: null as string | null,
name: c.nameTr || c.nameEn, name: c.nameTr || c.nameEn,
nameOriginal: c.nameEn, nameOriginal: c.nameEn,
parentId: null as string | null, parentId: null as string | null,
@@ -82,6 +86,82 @@ export class CategoriesService {
} }
} }
// ── PSA (Citroën/Peugeot): gerçek scope'ları session ile çek ──
// rawData.categories'de nav linkler var (Portal, vehicle.action, vin-group) — gerçek parça
// kategorileri değil. Bu yüzden rawData bypass edip PSA session flow'u çağırıyoruz.
if (dbCategories.length === 0 && vehicle.rawData) {
const rawData = vehicle.rawData as any;
const catPath: string = rawData?.catalogInfo?.catalogPath ?? "";
const svcName: string = rawData?.catalogInfo?.serviceName ?? "";
if (catPath.startsWith("/psa/") && svcName && vehicle.vin) {
try {
const scopes = await this.pl24FordLegacyService.fetchCategoriesForPsaVin(svcName, vehicle.vin);
if (scopes.length > 0) {
const insertData = scopes.map((s) => ({
vehicleId,
catalogVehicleId: null as string | null,
name: s.nameTr || s.nameEn,
nameOriginal: s.nameEn,
parentId: null as string | null,
externalId: s.code,
linkPath: s.linkPath || null,
linkWid: null as string | null,
source: "pl24" as const,
}));
dbCategories = await this.db
.insert(categories)
.values(insertData)
.onConflictDoNothing()
.returning();
this.logger.log(`Stored ${dbCategories.length} PSA scope categories for ${vehicle.vin}`);
}
} catch (err) {
this.logger.warn(`PSA scope fetch failed for ${vehicleId}: ${(err as Error).message}`);
}
}
}
// P4 Legacy: categories already decoded from VIN HTML (rawData.categories)
// PSA araçları üstte işlendi — burada /psa/ path'lerini atla
if (dbCategories.length === 0 && vehicle.rawData) {
const rawData = vehicle.rawData as any;
const catPath: string = rawData?.catalogInfo?.catalogPath ?? "";
if (!catPath.startsWith("/psa/")) {
const decodedCats = Array.isArray(rawData?.categories)
? (rawData.categories as Array<{ code: string; nameEn: string; nameTr?: string; linkPath?: string; linkWid?: string }>)
: null;
if (decodedCats && decodedCats.length > 0) {
try {
const seenNames = new Set<string>();
const uniqueCats = decodedCats.filter((c) => {
const name = c.nameTr || c.nameEn;
if (seenNames.has(name)) return false;
seenNames.add(name);
return true;
});
const insertData = uniqueCats.map((c) => ({
vehicleId,
catalogVehicleId: null as string | null,
name: c.nameTr || c.nameEn,
nameOriginal: c.nameEn,
parentId: null as string | null,
externalId: c.code,
linkPath: c.linkPath || null,
linkWid: c.linkWid || null,
source: "pl24" as const,
}));
dbCategories = await this.db.insert(categories).values(insertData).onConflictDoNothing().returning();
this.logger.log(`Stored ${dbCategories.length} P4 legacy categories for ${vehicle.vin}`);
} catch (err) {
this.logger.warn(`P4 legacy category insert failed for ${vehicleId}: ${(err as Error).message}`);
}
}
}
}
// If still no categories, try PartsCatalogs // If still no categories, try PartsCatalogs
if (dbCategories.length === 0 && vehicle.rawData) { if (dbCategories.length === 0 && vehicle.rawData) {
const rawData = vehicle.rawData as any; const rawData = vehicle.rawData as any;
@@ -98,6 +178,7 @@ export class CategoriesService {
if (groups.length > 0) { if (groups.length > 0) {
const insertData = groups.map((g) => ({ const insertData = groups.map((g) => ({
vehicleId, vehicleId,
catalogVehicleId: null as string | null,
name: g.name, name: g.name,
nameOriginal: g.name, nameOriginal: g.name,
parentId: null as string | null, parentId: null as string | null,
@@ -154,6 +235,7 @@ export class CategoriesService {
.insert(categories) .insert(categories)
.values({ .values({
vehicleId, vehicleId,
catalogVehicleId: null as string | null,
name: node.name, name: node.name,
nameOriginal: node.name, nameOriginal: node.name,
parentId, parentId,
@@ -191,6 +273,7 @@ export class CategoriesService {
const insertData = uniqueCategories.map((c) => ({ const insertData = uniqueCategories.map((c) => ({
vehicleId, vehicleId,
catalogVehicleId: null as string | null,
name: c.nameTr || c.nameEn, name: c.nameTr || c.nameEn,
nameOriginal: c.nameEn, nameOriginal: c.nameEn,
parentId: null as string | null, parentId: null as string | null,
@@ -249,6 +332,8 @@ export class CategoriesService {
if (!category) throw new NotFoundException("Kategori bulunamadı"); if (!category) throw new NotFoundException("Kategori bulunamadı");
if (!category.vehicleId) return [];
const [vehicle] = await this.db const [vehicle] = await this.db
.select() .select()
.from(vehicles) .from(vehicles)
@@ -263,9 +348,10 @@ export class CategoriesService {
// PartsCatalogs subgroups (on-demand drill-down) // PartsCatalogs subgroups (on-demand drill-down)
if (category.source === "parts-catalogs" && rawData?.source === "parts-catalogs" && category.externalId) { if (category.source === "parts-catalogs" && rawData?.source === "parts-catalogs" && category.externalId) {
let subGroups: PcatGroup[] = [];
try { try {
const carParams = this.buildPcatCarParams(rawData.parameters); const carParams = this.buildPcatCarParams(rawData.parameters);
const subGroups = await this.partsCatalogsService.fetchGroups( subGroups = await this.partsCatalogsService.fetchGroups(
rawData.catalogId, rawData.catalogId,
rawData.carId, rawData.carId,
category.externalId, category.externalId,
@@ -273,8 +359,30 @@ export class CategoriesService {
); );
if (subGroups.length > 0) { if (subGroups.length > 0) {
const insertData = subGroups.map((g) => ({ // Guard: if the API returned root-level groups as a fallback (happens when
// the groupId is a leaf-item reference, not a real sub-group ID), all returned
// groups will match existing root-level category externalIds for this vehicle.
// In that case, skip insertion — this category has no real sub-groups.
const rootExtIds = await this.db
.select({ externalId: categories.externalId })
.from(categories)
.where(eq(categories.vehicleId, category.vehicleId!));
const rootOnlyIds = rootExtIds
.filter((r) => r.externalId)
.map((r) => r.externalId as string);
const rootExtSet = new Set(rootOnlyIds);
const realSubGroups = subGroups.filter((g) => !rootExtSet.has(g.id));
if (realSubGroups.length === 0) {
this.logger.warn(
`getChildren: API returned root-level fallback groups for ${categoryId} (externalId=${category.externalId}) — skipping insert`,
);
return [];
}
const insertData = realSubGroups.map((g) => ({
vehicleId: category.vehicleId, vehicleId: category.vehicleId,
catalogVehicleId: category.catalogVehicleId,
name: g.name, name: g.name,
nameOriginal: g.name, nameOriginal: g.name,
parentId: categoryId, parentId: categoryId,
@@ -303,7 +411,18 @@ export class CategoriesService {
this.logger.error(`PartsCatalogs subgroup fetch failed for ${categoryId} (externalId=${category.externalId}): ${(err as Error).message}`); this.logger.error(`PartsCatalogs subgroup fetch failed for ${categoryId} (externalId=${category.externalId}): ${(err as Error).message}`);
} }
return children.length > 0 ? this.enrichWithSchemaImages(children) : children; if (children.length > 0) {
const enriched = await this.enrichWithSchemaImages(children);
// Use the API's hasSubgroups flag to correctly mark leaves vs parents.
// enrichWithSchemaImages only checks dbChildCount (always 0 for fresh inserts),
// so without this override, all sub-groups would be misidentified as leaves.
const hasSubgroupsMap = new Map(subGroups.map((g) => [g.id, g.hasSubgroups]));
return enriched.map((c: any) => ({
...c,
children: hasSubgroupsMap.get(c.externalId) === false ? [] : c.children,
}));
}
return children;
} }
if (!catalogInfo?.serviceName || !linkPath) { if (!catalogInfo?.serviceName || !linkPath) {
@@ -311,7 +430,8 @@ export class CategoriesService {
} }
// BOM / servicepart item links are leaf categories — they return parts, not subgroups // BOM / servicepart item links are leaf categories — they return parts, not subgroups
if (linkPath.includes("/bom/") || linkPath.includes("/bomdetails") || linkPath.includes("/partinfo/") || linkPath.includes("/servicepart/vin_items")) { const lp = linkPath.toLowerCase();
if (lp.includes("/bom/") || lp.includes("/bomdetails") || lp.includes("/partinfo/") || lp.includes("/servicepart/vin_items")) {
return []; return [];
} }
@@ -331,6 +451,7 @@ export class CategoriesService {
const insertData = uniqueSubGroups.map((sg) => ({ const insertData = uniqueSubGroups.map((sg) => ({
vehicleId: category.vehicleId, vehicleId: category.vehicleId,
catalogVehicleId: category.catalogVehicleId,
name: sg.name, name: sg.name,
nameOriginal: sg.name, nameOriginal: sg.name,
parentId: categoryId, parentId: categoryId,
@@ -377,16 +498,11 @@ export class CategoriesService {
if (!category) throw new NotFoundException("Kategori bulunamadı"); if (!category) throw new NotFoundException("Kategori bulunamadı");
// Check if this category has children // Check if this category has children
let children = await this.db const children = await this.db
.select() .select()
.from(categories) .from(categories)
.where(eq(categories.parentId, categoryId)); .where(eq(categories.parentId, categoryId));
// For parts-catalogs categories with no DB children, fetch from API first
if (children.length === 0 && category.source === "parts-catalogs" && category.linkPath?.startsWith("pcat:")) {
children = await this.getChildren(categoryId);
}
if (children.length > 0) { if (children.length > 0) {
return { return {
id: category.id, id: category.id,
@@ -400,7 +516,28 @@ export class CategoriesService {
}; };
} }
// PSA parent nodes — always fetch children on-demand:
// • psa:: scope paths (top-level scopes)
// • json-illustrations.action paths (mid-level main groups → illustration lists)
const isPsaParent =
category.linkPath?.startsWith("psa::") ||
(category.linkPath?.includes("/psa/") && category.linkPath?.includes("json-illustrations.action"));
if (isPsaParent && category.vehicleId) {
const psaChildren = await this.getChildren(categoryId);
return {
id: category.id,
name: category.name,
description: category.nameOriginal || null,
parentId: category.parentId || null,
parts: [],
schemaPics: [],
hotspots: [],
children: psaChildren,
};
}
// Leaf category — get or fetch parts // Leaf category — get or fetch parts
let discoveredChildren: any[] = [];
let dbParts = await this.db let dbParts = await this.db
.select() .select()
.from(parts) .from(parts)
@@ -420,11 +557,13 @@ export class CategoriesService {
} }
if ((needParts || needImage) && category.linkPath) { if ((needParts || needImage) && category.linkPath) {
const [vehicle] = await this.db const [vehicle] = category.vehicleId
? await this.db
.select() .select()
.from(vehicles) .from(vehicles)
.where(eq(vehicles.id, category.vehicleId)) .where(eq(vehicles.id, category.vehicleId))
.limit(1); .limit(1)
: [];
if (vehicle && category.source === "parts-catalogs" && category.linkPath?.startsWith("pcat:")) { if (vehicle && category.source === "parts-catalogs" && category.linkPath?.startsWith("pcat:")) {
// PartsCatalogs: fetch parts + schema image via API // PartsCatalogs: fetch parts + schema image via API
@@ -536,8 +675,10 @@ export class CategoriesService {
} catch (err) { } catch (err) {
const msg = (err as Error).message; const msg = (err as Error).message;
this.logger.error(`Failed to fetch PartsCatalogs parts for category ${categoryId}: ${msg}`); this.logger.error(`Failed to fetch PartsCatalogs parts for category ${categoryId}: ${msg}`);
// HTTP 400 = upstream API has no parts for this group; mark unavailable to prevent infinite retries // HTTP 400 = upstream API has no direct parts for this group — it may be a parent group
if (msg.includes("HTTP 400")) { if (msg.includes("HTTP 400")) {
discoveredChildren = await this.getChildren(categoryId);
if (discoveredChildren.length === 0) {
await this.db await this.db
.update(categories) .update(categories)
.set({ unavailable: true }) .set({ unavailable: true })
@@ -545,6 +686,7 @@ export class CategoriesService {
this.logger.warn(`Marked category ${categoryId} as unavailable (empty group from PartsCatalogs)`); this.logger.warn(`Marked category ${categoryId} as unavailable (empty group from PartsCatalogs)`);
} }
} }
}
} else if (vehicle && category.source === "emex") { } else if (vehicle && category.source === "emex") {
// EMEX: fetch parts + schema image via Puppeteer from QuickDetails URL // EMEX: fetch parts + schema image via Puppeteer from QuickDetails URL
try { try {
@@ -642,7 +784,7 @@ export class CategoriesService {
name: p.name, name: p.name,
nameOriginal: p.name, nameOriginal: p.name,
description: p.description || null, description: p.description || null,
quantity: p.quantity || null, quantity: p.quantity ? (parseInt(String(p.quantity), 10) || null) : null,
position: p.positionCode || null, position: p.positionCode || null,
hotspotIndex: p.hotspotId ? (() => { hotspotIndex: p.hotspotId ? (() => {
const val = parseInt(p.hotspotId!, 10); const val = parseInt(p.hotspotId!, 10);
@@ -659,9 +801,55 @@ export class CategoriesService {
} }
// Store schema image if available // Store schema image if available
if (needImage && pl24Result.schemaImageUrl) { // PSA: if cache hit returned no buffer, re-fetch fresh to get the image
const isPsaBoard = category.linkPath.includes("/psa/") && category.linkPath.includes("image-board.action");
if (needImage && isPsaBoard && !pl24Result.schemaImageBuffer) {
try {
const freshResult = await this.pl24FordLegacyService.fetchPsaParts(
category.linkPath, catalogInfo.serviceName, "_all_", "_all_", "_all_", true,
);
if (freshResult.schemaImageBuffer) {
(pl24Result as any).schemaImageBuffer = freshResult.schemaImageBuffer;
(pl24Result as any).schemaImageContentType = freshResult.schemaImageContentType;
(pl24Result as any).schemaWidth = freshResult.schemaWidth;
(pl24Result as any).schemaHeight = freshResult.schemaHeight;
(pl24Result as any).hotspots = freshResult.hotspots;
}
} catch (refetchErr) {
this.logger.warn(`PSA image re-fetch failed for ${categoryId}: ${(refetchErr as Error).message}`);
}
}
if (needImage && (pl24Result.schemaImageBuffer || (!isPsaBoard && pl24Result.schemaImageUrl))) {
// PSA: image already downloaded as buffer — upload directly to MinIO
if (pl24Result.schemaImageBuffer) {
try {
const ct = pl24Result.schemaImageContentType || "image/png";
const ext = ct.includes("gif") ? "gif" : "png";
const key = `schemas/psa-${categoryId}.${ext}`;
const minioUrl = await this.storage.upload(key, pl24Result.schemaImageBuffer, ct);
const hotspotsData = {
width: pl24Result.schemaWidth || null,
height: pl24Result.schemaHeight || null,
items: pl24Result.hotspots || [],
};
const [inserted] = await this.db
.insert(schemaPics)
.values({
categoryId,
imageUrl: minioUrl,
hotspots: JSON.stringify(hotspotsData),
source: "pl24",
})
.returning();
pics.push(inserted);
this.logger.log(`Stored PSA schema image for category ${categoryId}: ${minioUrl}`);
} catch (imgErr) {
this.logger.warn(`Failed to upload PSA schema image: ${(imgErr as Error).message}`);
}
} else {
// P5 REST: download via getSchemaImage
const imageResult = await this.pl24Service.getSchemaImage( const imageResult = await this.pl24Service.getSchemaImage(
pl24Result.schemaImageUrl, pl24Result.schemaImageUrl!,
catalogInfo.serviceName, catalogInfo.serviceName,
); );
@@ -687,6 +875,7 @@ export class CategoriesService {
pics.push(inserted); pics.push(inserted);
} }
} }
}
} catch (err) { } catch (err) {
this.logger.error(`Failed to fetch parts for category ${categoryId}: ${(err as Error).message}`); this.logger.error(`Failed to fetch parts for category ${categoryId}: ${(err as Error).message}`);
} }
@@ -694,6 +883,20 @@ export class CategoriesService {
} }
} }
// If fetchParts revealed this is actually a parent group (HTTP 400 → sub-groups found), return children
if (discoveredChildren.length > 0) {
return {
id: category.id,
name: category.name,
description: category.nameOriginal || null,
parentId: category.parentId || null,
parts: [],
schemaPics: [],
hotspots: [],
children: discoveredChildren,
};
}
// Parse hotspots data (may include width/height metadata) // Parse hotspots data (may include width/height metadata)
let hotspots: any[] = []; let hotspots: any[] = [];
let schemaWidth = 0; let schemaWidth = 0;
@@ -803,7 +1006,7 @@ export class CategoriesService {
? (!!c.linkPath && dbChildCount === 0) ? (!!c.linkPath && dbChildCount === 0)
: c.source === "parts-catalogs" : c.source === "parts-catalogs"
? (!!c.linkPath?.startsWith("pcat:") && dbChildCount === 0) ? (!!c.linkPath?.startsWith("pcat:") && dbChildCount === 0)
: (c.linkPath?.includes("/bom/") || c.linkPath?.includes("/bomdetails") || c.linkPath?.includes("/partinfo/") || c.linkPath?.includes("/servicepart/vin_items") || (!c.linkPath && dbChildCount === 0)); : (c.linkPath?.toLowerCase()?.includes("/bom/") || c.linkPath?.toLowerCase()?.includes("/bomdetails") || c.linkPath?.toLowerCase()?.includes("/partinfo/") || c.linkPath?.toLowerCase()?.includes("/servicepart/vin_items") || (!c.linkPath && dbChildCount === 0));
return { return {
...c, ...c,
schemaImageUrl: picMap.get(c.id) || null, schemaImageUrl: picMap.get(c.id) || null,

View File

@@ -231,6 +231,36 @@ export const oemCodeCopies = pgTable(
], ],
); );
// ─── Catalog Vehicles (VIN-less catalog browse — one record per PL24 vehicleId) ──
export const catalogVehicles = pgTable(
"catalog_vehicles",
{
id: uuid("id").primaryKey().defaultRandom(),
source: varchar("source", { length: 20 }).default("pl24").notNull(),
serviceName: varchar("service_name", { length: 100 }).notNull(),
brandName: varchar("brand_name", { length: 100 }).notNull(),
brandId: uuid("brand_id").references(() => brands.id),
model: varchar("model", { length: 255 }).notNull(),
year: varchar("year", { length: 50 }),
engine: varchar("engine", { length: 255 }),
bodyType: varchar("body_type", { length: 100 }),
transmission: varchar("transmission", { length: 100 }),
market: varchar("market", { length: 100 }),
serviceVehicleId: varchar("service_vehicle_id", { length: 255 }).notNull(),
catalogPath: text("catalog_path"),
architecture: varchar("architecture", { length: 30 }),
metadata: jsonb("metadata"),
categoriesFetched: boolean("categories_fetched").default(false).notNull(),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
},
(table) => [
uniqueIndex("catalog_vehicles_source_vid_idx").on(table.source, table.serviceVehicleId),
index("catalog_vehicles_brand_name_idx").on(table.brandName),
index("catalog_vehicles_service_name_idx").on(table.serviceName),
],
);
// ─── Vehicles (shared config — one record per VIN) ── // ─── Vehicles (shared config — one record per VIN) ──
export const vehicles = pgTable( export const vehicles = pgTable(
"vehicles", "vehicles",
@@ -280,13 +310,12 @@ export const categories = pgTable(
"categories", "categories",
{ {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),
vehicleId: uuid("vehicle_id") vehicleId: uuid("vehicle_id").references(() => vehicles.id, { onDelete: "cascade" }),
.notNull() catalogVehicleId: uuid("catalog_vehicle_id").references(() => catalogVehicles.id, { onDelete: "cascade" }),
.references(() => vehicles.id, { onDelete: "cascade" }),
name: varchar("name", { length: 500 }).notNull(), name: varchar("name", { length: 500 }).notNull(),
nameOriginal: varchar("name_original", { length: 500 }), nameOriginal: varchar("name_original", { length: 500 }),
parentId: uuid("parent_id"), parentId: uuid("parent_id"),
externalId: varchar("external_id", { length: 500 }), externalId: text("external_id"),
linkPath: text("link_path"), linkPath: text("link_path"),
linkWid: varchar("link_wid", { length: 100 }), linkWid: varchar("link_wid", { length: 100 }),
unavailable: boolean("unavailable").default(false).notNull(), unavailable: boolean("unavailable").default(false).notNull(),
@@ -295,8 +324,9 @@ export const categories = pgTable(
}, },
(table) => [ (table) => [
index("categories_vehicle_id_idx").on(table.vehicleId), index("categories_vehicle_id_idx").on(table.vehicleId),
index("categories_catalog_vehicle_id_idx").on(table.catalogVehicleId),
index("categories_parent_id_idx").on(table.parentId), index("categories_parent_id_idx").on(table.parentId),
uniqueIndex("categories_vehicle_name_source_idx").on(table.vehicleId, table.name, table.source), uniqueIndex("categories_vehicle_name_source_idx").on(table.vehicleId, table.catalogVehicleId, table.name, table.source),
], ],
); );
@@ -305,9 +335,8 @@ export const parts = pgTable(
"parts", "parts",
{ {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),
vehicleId: uuid("vehicle_id") vehicleId: uuid("vehicle_id").references(() => vehicles.id, { onDelete: "cascade" }),
.notNull() catalogVehicleId: uuid("catalog_vehicle_id").references(() => catalogVehicles.id, { onDelete: "cascade" }),
.references(() => vehicles.id, { onDelete: "cascade" }),
categoryId: uuid("category_id") categoryId: uuid("category_id")
.notNull() .notNull()
.references(() => categories.id, { onDelete: "cascade" }), .references(() => categories.id, { onDelete: "cascade" }),
@@ -327,6 +356,7 @@ export const parts = pgTable(
}, },
(table) => [ (table) => [
index("parts_vehicle_id_idx").on(table.vehicleId), index("parts_vehicle_id_idx").on(table.vehicleId),
index("parts_catalog_vehicle_id_idx").on(table.catalogVehicleId),
index("parts_category_id_idx").on(table.categoryId), index("parts_category_id_idx").on(table.categoryId),
index("parts_oem_code_idx").on(table.oemCode), index("parts_oem_code_idx").on(table.oemCode),
], ],

View File

@@ -15,6 +15,7 @@ import {
parts, parts,
schemaPics, schemaPics,
referrals, referrals,
catalogVehicles,
} from "./core"; } from "./core";
export const usersRelations = relations(users, ({ many }) => ({ export const usersRelations = relations(users, ({ many }) => ({
@@ -59,6 +60,13 @@ export const userBrandsRelations = relations(userBrands, ({ one }) => ({
export const brandsRelations = relations(brands, ({ many }) => ({ export const brandsRelations = relations(brands, ({ many }) => ({
userBrands: many(userBrands), userBrands: many(userBrands),
catalogVehicles: many(catalogVehicles),
}));
export const catalogVehiclesRelations = relations(catalogVehicles, ({ one, many }) => ({
brand: one(brands, { fields: [catalogVehicles.brandId], references: [brands.id] }),
categories: many(categories),
parts: many(parts),
})); }));
export const paymentsRelations = relations(payments, ({ one }) => ({ export const paymentsRelations = relations(payments, ({ one }) => ({
@@ -88,6 +96,7 @@ export const userVehiclesRelations = relations(userVehicles, ({ one }) => ({
export const categoriesRelations = relations(categories, ({ one, many }) => ({ export const categoriesRelations = relations(categories, ({ one, many }) => ({
vehicle: one(vehicles, { fields: [categories.vehicleId], references: [vehicles.id] }), vehicle: one(vehicles, { fields: [categories.vehicleId], references: [vehicles.id] }),
catalogVehicle: one(catalogVehicles, { fields: [categories.catalogVehicleId], references: [catalogVehicles.id] }),
parent: one(categories, { parent: one(categories, {
fields: [categories.parentId], fields: [categories.parentId],
references: [categories.id], references: [categories.id],
@@ -100,6 +109,7 @@ export const categoriesRelations = relations(categories, ({ one, many }) => ({
export const partsRelations = relations(parts, ({ one }) => ({ export const partsRelations = relations(parts, ({ one }) => ({
vehicle: one(vehicles, { fields: [parts.vehicleId], references: [vehicles.id] }), vehicle: one(vehicles, { fields: [parts.vehicleId], references: [vehicles.id] }),
catalogVehicle: one(catalogVehicles, { fields: [parts.catalogVehicleId], references: [catalogVehicles.id] }),
category: one(categories, { fields: [parts.categoryId], references: [categories.id] }), category: one(categories, { fields: [parts.categoryId], references: [categories.id] }),
})); }));

View File

@@ -4,33 +4,43 @@ import postgres from "postgres";
import { brands, plans, users, accounts } from "./schema/core"; import { brands, plans, users, accounts } from "./schema/core";
const BRANDS_DATA = [ const BRANDS_DATA = [
{ name: "BMW", slug: "bmw" }, // Mevcut markalar
{ name: "Mercedes-Benz", slug: "mercedes-benz" },
{ name: "Audi", slug: "audi" }, { name: "Audi", slug: "audi" },
{ name: "Volkswagen", slug: "volkswagen" }, { name: "BMW", slug: "bmw" },
{ name: "Fiat", slug: "fiat" },
{ name: "Renault", slug: "renault" },
{ name: "Peugeot", slug: "peugeot" },
{ name: "Citroen", slug: "citroen" }, { name: "Citroen", slug: "citroen" },
{ name: "Toyota", slug: "toyota" }, { name: "Dacia", slug: "dacia" },
{ name: "Fiat", slug: "fiat" },
{ name: "Ford", slug: "ford" },
{ name: "Honda", slug: "honda" }, { name: "Honda", slug: "honda" },
{ name: "Hyundai", slug: "hyundai" }, { name: "Hyundai", slug: "hyundai" },
{ name: "Kia", slug: "kia" },
{ name: "Ford", slug: "ford" },
{ name: "Opel", slug: "opel" },
{ name: "Skoda", slug: "skoda" },
{ name: "Seat", slug: "seat" },
{ name: "Volvo", slug: "volvo" },
{ name: "Nissan", slug: "nissan" },
{ name: "Mazda", slug: "mazda" },
{ name: "Porsche", slug: "porsche" },
{ name: "Land Rover", slug: "land-rover" },
{ name: "Jaguar", slug: "jaguar" }, { name: "Jaguar", slug: "jaguar" },
{ name: "Kia", slug: "kia" },
{ name: "Land Rover", slug: "land-rover" },
{ name: "Mazda", slug: "mazda" },
{ name: "Mercedes-Benz", slug: "mercedes-benz" },
{ name: "Mini", slug: "mini" }, { name: "Mini", slug: "mini" },
{ name: "Dacia", slug: "dacia" }, { name: "Mitsubishi", slug: "mitsubishi" },
{ name: "Nissan", slug: "nissan" },
{ name: "Opel", slug: "opel" },
{ name: "Peugeot", slug: "peugeot" },
{ name: "Porsche", slug: "porsche" },
{ name: "Renault", slug: "renault" },
{ name: "Seat", slug: "seat" },
{ name: "Skoda", slug: "skoda" },
{ name: "Subaru", slug: "subaru" }, { name: "Subaru", slug: "subaru" },
{ name: "Suzuki", slug: "suzuki" }, { name: "Suzuki", slug: "suzuki" },
{ name: "Mitsubishi", slug: "mitsubishi" }, { name: "Toyota", slug: "toyota" },
{ name: "Volkswagen", slug: "volkswagen" },
{ name: "Volvo", slug: "volvo" },
// PL24 kataloglarında olan, sase.tr'ye eklenen markalar
{ name: "Alpine", slug: "alpine" },
{ name: "Bentley", slug: "bentley" },
{ name: "Cupra", slug: "cupra" },
{ name: "Infiniti", slug: "infiniti" },
{ name: "Lexus", slug: "lexus" },
{ name: "MAN", slug: "man" },
{ name: "Polestar", slug: "polestar" },
{ name: "Smart", slug: "smart" },
]; ];
const PLANS_DATA = [ const PLANS_DATA = [

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,7 @@ import {
getServiceApiPath, getServiceApiPath,
getServiceConfig, getServiceConfig,
isP5Modern, isP5Modern,
isLegacyArchitecture,
SERVICE_TO_BRAND, SERVICE_TO_BRAND,
} from "./pl24.types"; } from "./pl24.types";
@@ -76,14 +77,12 @@ export class PL24Service {
); );
} }
// Dispatch legacy architectures to their dedicated services // Dispatch P4 legacy architectures to the generic legacy service
if (!isP5Modern(serviceName)) { if (!isP5Modern(serviceName)) {
if (serviceName === "fordt_parts") { if (isLegacyArchitecture(serviceName)) {
return this.fordLegacyService.decodeVin(cleanVin); return this.fordLegacyService.decodeVinForService(cleanVin, serviceName);
} }
this.logger.warn( this.logger.warn(`Unknown architecture for service: ${serviceName}`);
`Legacy architecture not supported yet: ${serviceName}`,
);
return null; return null;
} }
@@ -255,11 +254,18 @@ export class PL24Service {
async fetchPartsByPath( async fetchPartsByPath(
linkPath: string, linkPath: string,
serviceName: string, serviceName: string,
body?: string,
engine?: string,
gearbox?: string,
): Promise<PL24PartsResponse> { ): Promise<PL24PartsResponse> {
// Ford legacy dispatch // Ford legacy dispatch
if (this.isFordLegacyPath(linkPath)) { if (this.isP4LegacyPath(linkPath)) {
return this.fordLegacyService.fetchPartsByPath(linkPath, serviceName); return this.fordLegacyService.fetchPartsByPath(linkPath, serviceName);
} }
// PSA image-board dispatch
if (this.isPsaBoardPath(linkPath)) {
return this.fordLegacyService.fetchPsaParts(linkPath, serviceName, body, engine, gearbox);
}
await this.touchActivity(); await this.touchActivity();
const pathHash = createHash("sha256").update(linkPath).digest("hex").substring(0, 16); const pathHash = createHash("sha256").update(linkPath).digest("hex").substring(0, 16);
@@ -378,11 +384,22 @@ export class PL24Service {
async fetchSubGroupsByPath( async fetchSubGroupsByPath(
linkPath: string, linkPath: string,
serviceName: string, serviceName: string,
body?: string,
engine?: string,
gearbox?: string,
): Promise<PL24MainGroup[]> { ): Promise<PL24MainGroup[]> {
// Ford legacy dispatch // Ford legacy dispatch
if (this.isFordLegacyPath(linkPath)) { if (this.isP4LegacyPath(linkPath)) {
return this.fordLegacyService.fetchSubGroupsByPath(linkPath, serviceName); return this.fordLegacyService.fetchSubGroupsByPath(linkPath, serviceName);
} }
// PSA scope dispatch ("psa::{svc}::scope=..." → main groups)
if (this.isPsaPath(linkPath)) {
return this.fordLegacyService.fetchPsaSubGroups(linkPath, body, engine, gearbox);
}
// PSA illustrations dispatch (/psa/.../json-illustrations.action → illustrations)
if (this.isPsaIllusPath(linkPath)) {
return this.fordLegacyService.fetchPsaIllustrations(linkPath, serviceName, body, engine, gearbox);
}
this.logger.log(`Fetching sub-groups by path: ${linkPath}`); this.logger.log(`Fetching sub-groups by path: ${linkPath}`);
await this.touchActivity(); await this.touchActivity();
@@ -406,6 +423,122 @@ export class PL24Service {
} }
} }
/**
* Fetch category tree scopes for a PSA legacy catalog vehicle.
* Delegates to fordLegacyService which handles PSA HTML scraping flow.
*/
async fetchMainGroupsForPsa(
serviceName: string,
familyId: string,
salesTypeId: string,
mode: string,
upds: string,
body?: string,
engine?: string,
gearbox?: string,
): Promise<PL24DecodedCategory[]> {
return this.fordLegacyService.fetchMainGroupsForPsa(
serviceName,
familyId,
salesTypeId,
mode,
upds,
body,
engine,
gearbox,
);
}
/**
* Fetch body types for a PSA catalog vehicle variant selector.
*/
async fetchPsaBodies(
svc: string,
familyId: string,
salesTypeId: string,
mode: string,
upds: string,
): Promise<{ code: string; name: string }[]> {
return this.fordLegacyService.fetchPsaBodies(svc, familyId, salesTypeId, mode, upds);
}
/**
* Fetch engines for a PSA catalog vehicle given a selected body code.
*/
async fetchPsaEnginesForBody(
svc: string,
familyId: string,
salesTypeId: string,
bodyCode: string,
mode: string,
upds: string,
): Promise<{ code: string; name: string }[]> {
return this.fordLegacyService.fetchPsaEnginesForBody(svc, familyId, salesTypeId, bodyCode, mode, upds);
}
/**
* Fetch gearboxes for a PSA catalog vehicle given selected body + engine codes.
*/
async fetchPsaGearboxes(
svc: string,
familyId: string,
salesTypeId: string,
bodyCode: string,
engineCode: string,
mode: string,
upds: string,
): Promise<{ code: string; name: string }[]> {
return this.fordLegacyService.fetchPsaGearboxes(svc, familyId, salesTypeId, bodyCode, engineCode, mode, upds);
}
/**
* Fetch model config (variant options) for a Ford catalog vehicle.
*/
async fetchFordModelConfig(
svc: string,
familyId: string,
mode: string,
upds: string,
): Promise<{
modelYears: { code: string; name: string }[];
engines: { code: string; name: string }[];
gearboxes: { code: string; name: string }[];
}> {
return this.fordLegacyService.fetchFordModelConfig(svc, familyId, mode, upds);
}
/**
* Fetch model config (year variant options) for a Volvo catalog vehicle.
*/
async fetchVolvoModelConfig(
svc: string,
mdlId: string,
mode: string,
upds: string,
): Promise<{
modelYears: { code: string; name: string }[];
engines: { code: string; name: string }[];
gearboxes: { code: string; name: string }[];
}> {
return this.fordLegacyService.fetchVolvoModelConfig(svc, mdlId, mode, upds);
}
/**
* Fetch main category groups for a Ford catalog vehicle variant.
*/
async fetchFordMainGroups(
svc: string,
familyId: string,
modelYear: string,
engine: string,
gearbox: string,
mode: string,
upds: string,
catCode?: string,
): Promise<PL24DecodedCategory[]> {
return this.fordLegacyService.fetchFordMainGroups(svc, familyId, modelYear, engine, gearbox, mode, upds, catCode);
}
/** /**
* Re-fetch main groups using a stored mainGroupsPath. * Re-fetch main groups using a stored mainGroupsPath.
*/ */
@@ -414,6 +547,21 @@ export class PL24Service {
mainGroupsPath: string, mainGroupsPath: string,
): Promise<PL24DecodedCategory[]> { ): Promise<PL24DecodedCategory[]> {
await this.touchActivity(); await this.touchActivity();
// Ford legacy catalog vehicles store the vehicle.action URL as catalogPath.
// Dispatch to fordLegacyService which fetches and extracts group links from the HTML.
if (this.isP4LegacyPath(mainGroupsPath)) {
const groups = await this.fordLegacyService.fetchSubGroupsByPath(mainGroupsPath, serviceName);
return groups.map((g) => ({
code: g.code,
nameEn: g.name,
nameTr: g.name,
description: g.description || null,
iconUrl: g.iconUrl || null,
subGroups: [],
linkPath: g.linkPath,
linkWid: g.linkWid,
}));
}
try { try {
await this.authService.authorizeService(serviceName); await this.authService.authorizeService(serviceName);
const headers = await this.authService.buildAuthHeaders(serviceName); const headers = await this.authService.buildAuthHeaders(serviceName);
@@ -553,6 +701,15 @@ export class PL24Service {
return isP5Modern(serviceName) || serviceName === "fordt_parts"; return isP5Modern(serviceName) || serviceName === "fordt_parts";
} }
/**
* Returns true if this VIN's WMI maps to any PL24 service (P5 Modern or P4 Legacy).
* Use this to gate VIN decode attempts; use isSupported() for catalog browser eligibility.
*/
isDecodeable(vin: string): boolean {
if (!vin || vin.length < 3) return false;
return !!this.getServiceName(vin);
}
/** /**
* Get supported brands list. * Get supported brands list.
*/ */
@@ -1017,7 +1174,9 @@ export class PL24Service {
} }
const partRecords = records.filter( const partRecords = records.filter(
(record) => record.characteristic !== "sectionrow" && record.partno, (record) =>
record.characteristic !== "sectionrow" &&
(record.partno || (record.values as Record<string, unknown>)?.partno),
); );
return partRecords.map((part) => { return partRecords.map((part) => {
@@ -1152,7 +1311,9 @@ export class PL24Service {
const mercedesMatch = imageUrl.match(/[?&]illu=([a-zA-Z0-9_]+)/); const mercedesMatch = imageUrl.match(/[?&]illu=([a-zA-Z0-9_]+)/);
if (mercedesMatch) return mercedesMatch[1]; if (mercedesMatch) return mercedesMatch[1];
return null; // PSA and other legacy brands use ticket-based URLs that don't match above patterns.
// Fall back to a hash of the URL so caching still works.
return createHash("sha256").update(imageUrl).digest("hex").substring(0, 24);
} }
// ==================== PRIVATE: Brand-specific flows ==================== // ==================== PRIVATE: Brand-specific flows ====================
@@ -1183,8 +1344,20 @@ export class PL24Service {
return `${url.pathname}?${url.searchParams.toString()}`; return `${url.pathname}?${url.searchParams.toString()}`;
} }
private isFordLegacyPath(linkPath: string): boolean { private isP4LegacyPath(linkPath: string): boolean {
return linkPath.includes("/ford/") && linkPath.includes(".action"); return linkPath.includes(".action");
}
private isPsaPath(linkPath: string): boolean {
return linkPath.startsWith("psa::");
}
private isPsaIllusPath(linkPath: string): boolean {
return linkPath.includes("/psa/") && linkPath.includes("json-illustrations.action");
}
private isPsaBoardPath(linkPath: string): boolean {
return linkPath.includes("/psa/") && linkPath.includes("image-board.action");
} }
private isDaimlerService(serviceName: string): boolean { private isDaimlerService(serviceName: string): boolean {
@@ -1540,6 +1713,237 @@ export class PL24Service {
} }
} }
// ==================== PUBLIC: Catalog browse (VIN-less) ====================
/**
* Fetch a list of vehicles/models for a service (VIN-less catalog browse).
* Tries P5 Modern selection wizard endpoints.
* Returns empty array if unavailable (requires discovery to find correct endpoint).
*/
async fetchVehicleList(serviceName: string): Promise<
Array<{
vehicleId: string;
model: string;
year?: string;
engine?: string;
bodyType?: string;
transmission?: string;
market?: string;
catalogPath?: string;
metadata?: Record<string, unknown>;
}>
> {
await this.touchActivity();
// Legacy architecture dispatch
const serviceConfig = getServiceConfig(serviceName);
if (serviceConfig?.architecture === "LEGACY_PSA") {
return this.fordLegacyService.fetchVehicleListForPsa(serviceName);
}
if (serviceConfig?.architecture === "LEGACY_FORD") {
return this.fordLegacyService.fetchVehicleListForFord(serviceName);
}
if (serviceConfig?.architecture === "LEGACY_HYUNDAI_KIA") {
return this.fordLegacyService.fetchVehicleListForHyundaiKia(serviceName);
}
if (serviceConfig?.architecture === "LEGACY_NISSAN") {
return this.fordLegacyService.fetchVehicleListForNissan(serviceName);
}
if (serviceConfig?.architecture === "LEGACY_OPEL") {
return this.fordLegacyService.fetchVehicleListForOpel(serviceName);
}
if (serviceConfig?.architecture === "LEGACY_VOLVO") {
return this.fordLegacyService.fetchVehicleListForVolvo(serviceName);
}
const cacheKey = `${PL24_DEFAULTS.CACHE_PREFIX}vehicle_list:${serviceName}`;
const cached = await this.redis.getJson<any[]>(cacheKey);
if (cached) return cached;
try {
await this.authService.authorizeService(serviceName);
const headers = await this.authService.buildAuthHeaders(serviceName);
const catalogBase = getServiceApiPath(serviceName);
// Discovered via Playwright explorer (scripts/pl24-catalog-explorer.js → docs/pl24-catalog/*.md)
// Each P5 backend uses a different initial model listing endpoint
const BACKEND_MODEL_PATH: Record<string, string> = {
p5vwag: "/extern/vehicle/modelfamilies", // VW, Audi, Skoda, SEAT, Cupra, Porsche, Bentley
p5bmw: "/extern/vehicle/models", // BMW, MINI, Motorrad
p5daimler: "/extern/vehicle/scope", // Mercedes-Benz, smart
p5renault: "/extern/vehicle/catalogs", // Renault, Dacia, Alpine
p5jlr: "/extern/vehicle/models", // Jaguar, Land Rover
p5toyota: "/extern/vehicle/modelFamilies", // Toyota, Lexus (capital F)
p5mitsubishi: "/extern/vehicles/vehiclesOverview", // Mitsubishi
p5suzuki: "/extern/vehicle/modelFamilies", // Suzuki
p5man: "/extern/model/categories", // MAN trucks
};
// catalogBase is like "/p5vwag" — strip leading slash for map lookup
const backendKey = catalogBase.replace(/^\//, "");
const modelPath = BACKEND_MODEL_PATH[backendKey] ?? "/extern/vehicle/modelfamilies";
const url = `${this.baseUrl}${catalogBase}${modelPath}?lang=${this.language}&serviceName=${serviceName}`;
const response = await fetch(url, {
method: "GET",
headers,
signal: AbortSignal.timeout(15000),
});
if (response.ok) {
const data = (await response.json()) as Record<string, any>;
let vehicles = this.parseVehicleListResponse(data, serviceName);
// p5daimler "scope" endpoint returns 1 record whose link.path points to "modeltype" (Smart).
// Follow that link to retrieve the actual model type list (C450C454).
if (vehicles.length === 1 && vehicles[0].catalogPath?.includes("modeltype")) {
const modeltypePath = vehicles[0].catalogPath;
const modeltypeUrl = modeltypePath.startsWith("http")
? modeltypePath
: `${this.baseUrl}${modeltypePath}`;
try {
const modeltypeResp = await fetch(modeltypeUrl, {
method: "GET",
headers,
signal: AbortSignal.timeout(15000),
});
if (modeltypeResp.ok) {
const modeltypeData = (await modeltypeResp.json()) as Record<string, any>;
const modeltypeVehicles = this.parseVehicleListResponse(modeltypeData, serviceName);
if (modeltypeVehicles.length > 0) {
this.logger.log(`Smart: modeltype returned ${modeltypeVehicles.length} models`);
vehicles = modeltypeVehicles;
}
} else {
this.logger.warn(`Smart: modeltype HTTP ${modeltypeResp.status}`);
}
} catch (err) {
this.logger.warn(`Smart: modeltype fetch failed: ${(err as Error).message}`);
}
}
if (vehicles.length > 0) {
await this.redis.setJson(cacheKey, vehicles, 86400); // 24h
return vehicles;
}
}
this.logger.log(`No vehicle list available for ${serviceName} (HTTP ${response.status})`);
return [];
} catch (err) {
this.logger.warn(`fetchVehicleList failed for ${serviceName}: ${(err as Error).message}`);
return [];
}
}
private parseVehicleListResponse(
data: Record<string, any>,
serviceName: string,
): Array<{
vehicleId: string;
model: string;
year?: string;
engine?: string;
bodyType?: string;
transmission?: string;
market?: string;
catalogPath?: string;
metadata?: Record<string, unknown>;
}> {
let records: any[] = [];
if (Array.isArray(data)) {
records = data;
} else if (Array.isArray(data.data?.records)) {
records = data.data.records;
} else if (Array.isArray(data.vehicles)) {
records = data.vehicles;
} else if (Array.isArray(data.models)) {
records = data.models;
} else if (Array.isArray(data.data)) {
records = data.data;
}
return records
.filter((r) => r.id || r.vehicleId || r.vid)
.map((r) => {
const values = r.values || {};
const vehicleId = String(r.id || r.vehicleId || r.vid || "");
// modelfamilies uses values.caption; older formats use values.model / r.description
const model =
values.caption || values.model || values.description || r.description || r.name || vehicleId;
const link = r.link || {};
return {
vehicleId,
model,
year: values.year || values.modelYear || r.year || undefined,
engine: values.engine || values.engineCode || undefined,
bodyType: values.bodyType || values.body || undefined,
transmission: values.transmission || undefined,
market: values.market || undefined,
catalogPath: link.path || undefined,
metadata: r,
};
});
}
/**
* Explore a P5 Modern service catalog — tries various endpoints and returns raw results.
* Used by admin endpoint for discovery.
*/
async exploreP5Service(serviceName: string): Promise<Record<string, any>> {
await this.touchActivity();
const results: Record<string, any> = {};
try {
await this.authService.authorizeService(serviceName);
const headers = await this.authService.buildAuthHeaders(serviceName);
const catalogBase = getServiceApiPath(serviceName);
const probeEndpoints = [
"extern/vehicles",
"extern/vehicleList",
"extern/models",
"extern/selection/vehicles",
"extern/selection/rootNode",
"extern/catalogs",
"extern/modelSeries",
];
await Promise.all(
probeEndpoints.map(async (endpoint) => {
const url = `${this.baseUrl}${catalogBase}/${endpoint}?lang=${this.language}&serviceName=${serviceName}`;
try {
const response = await fetch(url, {
method: "GET",
headers,
signal: AbortSignal.timeout(8000),
});
const status = response.status;
let body: any = null;
if (response.ok) {
try {
body = await response.json();
} catch {
body = await response.text();
}
}
results[endpoint] = { status, body: body ? JSON.stringify(body).substring(0, 2000) : null };
} catch (err) {
results[endpoint] = { error: (err as Error).message };
}
}),
);
} catch (err) {
results._authError = (err as Error).message;
}
return results;
}
private parseJlrIllustrations( private parseJlrIllustrations(
response: unknown, response: unknown,
): Array<{ btnr: number; name: string; code: string }> { ): Array<{ btnr: number; name: string; code: string }> {

View File

@@ -276,7 +276,7 @@ export const PL24_SERVICE_CATALOGS: Record<string, PL24CatalogConfig> = {
// Mitsubishi // Mitsubishi
mmc_parts: { mmc_parts: {
basePath: "/pl24-app/mmc_parts", basePath: "/pl24-app/mmc_parts",
apiPath: "/p5mmc", apiPath: "/p5mitsubishi",
architecture: "P5_MODERN", architecture: "P5_MODERN",
}, },
@@ -287,12 +287,84 @@ export const PL24_SERVICE_CATALOGS: Record<string, PL24CatalogConfig> = {
architecture: "P5_MODERN", architecture: "P5_MODERN",
}, },
// Ford // ==================== LEGACY P4 ARCHITECTURE ====================
fordt_parts: {
basePath: "/ford/fordt_parts", // PSA Group (Citroën, Peugeot)
apiPath: "/ford/fordt_parts", citroen_parts: {
basePath: "/psa",
apiPath: "/psa",
architecture: "LEGACY_PSA",
},
citroenDs_parts: {
basePath: "/psa",
apiPath: "/psa",
architecture: "LEGACY_PSA",
},
peugeot_parts: {
basePath: "/psa",
apiPath: "/psa",
architecture: "LEGACY_PSA",
},
// Ford Group
fordp_parts: {
basePath: "/ford",
apiPath: "/ford",
architecture: "LEGACY_FORD", architecture: "LEGACY_FORD",
}, },
fordt_parts: {
basePath: "/ford",
apiPath: "/ford",
architecture: "LEGACY_FORD",
},
// Hyundai-Kia Automotive Group
hyundai_parts: {
basePath: "/hyundai-kia-automotive-group",
apiPath: "/hyundai-kia-automotive-group",
architecture: "LEGACY_HYUNDAI_KIA",
},
kia_parts: {
basePath: "/hyundai-kia-automotive-group",
apiPath: "/hyundai-kia-automotive-group",
architecture: "LEGACY_HYUNDAI_KIA",
},
// Nissan/Infiniti
nissan_parts: {
basePath: "/nissan",
apiPath: "/nissan",
architecture: "LEGACY_NISSAN",
},
infiniti_parts: {
basePath: "/nissan",
apiPath: "/nissan",
architecture: "LEGACY_NISSAN",
},
// GM / Stellantis (Opel, Vauxhall)
opel_parts: {
basePath: "/opel",
apiPath: "/opel",
architecture: "LEGACY_OPEL",
},
vauxhall_parts: {
basePath: "/opel",
apiPath: "/opel",
architecture: "LEGACY_OPEL",
},
// Volvo/Polestar
volvo_parts: {
basePath: "/volvo",
apiPath: "/volvo",
architecture: "LEGACY_VOLVO",
},
polestar_parts: {
basePath: "/volvo",
apiPath: "/volvo",
architecture: "LEGACY_VOLVO",
},
}; };
// ==================== HELPER FUNCTIONS ==================== // ==================== HELPER FUNCTIONS ====================
@@ -436,11 +508,43 @@ export const PL24_WMI_SERVICE_MAP: Record<string, string> = {
MA3: "suzuki_parts", MA3: "suzuki_parts",
MBH: "suzuki_parts", MBH: "suzuki_parts",
// Ford // Ford Commercial (Transit vans — Turkey Otosan, etc.)
NM0: "fordt_parts", NM0: "fordt_parts",
WF0: "fordt_parts",
"1FA": "fordt_parts", // Ford Passenger (European passenger cars — Germany Cologne plant)
"3FA": "fordt_parts", WF0: "fordp_parts",
"1FA": "fordp_parts",
"3FA": "fordp_parts",
// Hyundai
KMH: "hyundai_parts", // Hyundai Korea Motor House
TMK: "hyundai_parts", // Hyundai (Turkey/other markets)
// Kia
KNA: "kia_parts", // Kia (worldwide production)
U5Y: "kia_parts", // Kia Slovakia
// Nissan
JN1: "nissan_parts", // Nissan Japan (passenger)
JN6: "nissan_parts", // Nissan Japan (pickup/van)
JN8: "nissan_parts", // Nissan Japan (SUV)
VNK: "nissan_parts", // Nissan UK/Europe
// Infiniti
JNK: "infiniti_parts", // Infiniti (Japan/Korea)
// Opel / Vauxhall
W0L: "opel_parts", // Opel AG (Germany)
// Citroën (PSA)
VF7: "citroen_parts", // Citroën SA (France)
// Peugeot (PSA)
VF3: "peugeot_parts", // Peugeot SA (France)
// Volvo
YV1: "volvo_parts", // Volvo Cars (Sweden)
YV4: "volvo_parts", // Volvo Cars (specific models)
}; };
// ==================== VEHICLE TYPES ==================== // ==================== VEHICLE TYPES ====================
@@ -451,6 +555,11 @@ export interface PL24CatalogInfo {
catalogPath: string; catalogPath: string;
baseUrl: string; baseUrl: string;
mainGroupsPath?: string; mainGroupsPath?: string;
// PSA VIN decode session parameters (set by decodeVinPsa)
psaFamilyId?: string;
psaSalesTypeId?: string;
psaMode?: string;
psaUpds?: string;
} }
export interface PL24MainGroup { export interface PL24MainGroup {
@@ -518,6 +627,8 @@ export interface PL24PartsResponse {
groupId: string; groupId: string;
groupName: string; groupName: string;
schemaImageUrl?: string; schemaImageUrl?: string;
schemaImageBuffer?: Buffer; // pre-downloaded buffer (PSA: ticket URLs expire quickly)
schemaImageContentType?: string;
schemaWidth?: number; schemaWidth?: number;
schemaHeight?: number; schemaHeight?: number;
parts: PL24Part[]; parts: PL24Part[];
@@ -589,37 +700,96 @@ export interface PL24DecodedPart {
// ==================== BRAND MAP ==================== // ==================== BRAND MAP ====================
export const SERVICE_TO_BRAND: Record<string, string> = { export const SERVICE_TO_BRAND: Record<string, string> = {
// Volkswagen Group
vw_parts: "Volkswagen", vw_parts: "Volkswagen",
vwclassic_parts: "Volkswagen", vwclassic_parts: "Volkswagen",
vn_parts: "Volkswagen", vn_parts: "Volkswagen",
audi_parts: "Audi", audi_parts: "Audi",
seat_parts: "SEAT", seat_parts: "Seat",
cupra_parts: "Cupra", cupra_parts: "Cupra",
skoda_parts: "Skoda", skoda_parts: "Skoda",
bentley_parts: "Bentley", bentley_parts: "Bentley",
// BMW Group
bmw_parts: "BMW", bmw_parts: "BMW",
bmwclassic_parts: "BMW", bmwclassic_parts: "BMW",
bmwmotorrad_parts: "BMW", bmwmotorrad_parts: "BMW",
bmwmotorradclassic_parts: "BMW", bmwmotorradclassic_parts: "BMW",
mini_parts: "MINI", mini_parts: "Mini",
miniclassic_parts: "MINI", miniclassic_parts: "Mini",
// Mercedes-Benz Group
mercedes_parts: "Mercedes-Benz", mercedes_parts: "Mercedes-Benz",
mercedesclassic_parts: "Mercedes-Benz", mercedesclassic_parts: "Mercedes-Benz",
mercedesvans_parts: "Mercedes-Benz", mercedesvans_parts: "Mercedes-Benz",
mercedestrucks_parts: "Mercedes-Benz", mercedestrucks_parts: "Mercedes-Benz",
mercedesunimog_parts: "Mercedes-Benz", mercedesunimog_parts: "Mercedes-Benz",
smart_parts: "smart", smart_parts: "Smart",
// Porsche (VAG backend)
porsche_parts: "Porsche", porsche_parts: "Porsche",
porscheclassic_parts: "Porsche", porscheclassic_parts: "Porsche",
// Toyota Group
toyota_parts: "Toyota", toyota_parts: "Toyota",
lexus_parts: "Lexus", lexus_parts: "Lexus",
// Renault Group
renault_parts: "Renault", renault_parts: "Renault",
dacia_parts: "Dacia", dacia_parts: "Dacia",
alpine_parts: "Alpine", alpine_parts: "Alpine",
// Jaguar Land Rover
jaguar_parts: "Jaguar", jaguar_parts: "Jaguar",
landrover_parts: "Land Rover", landrover_parts: "Land Rover",
// Other P5
man_parts: "MAN", man_parts: "MAN",
mmc_parts: "Mitsubishi", mmc_parts: "Mitsubishi",
suzuki_parts: "Suzuki", suzuki_parts: "Suzuki",
// PSA Group
citroen_parts: "Citroen",
citroenDs_parts: "Citroen",
peugeot_parts: "Peugeot",
// Ford Group
fordp_parts: "Ford",
fordt_parts: "Ford", fordt_parts: "Ford",
// Hyundai-Kia Group
hyundai_parts: "Hyundai",
kia_parts: "Kia",
// Nissan/Infiniti
nissan_parts: "Nissan",
infiniti_parts: "Infiniti",
// GM / Stellantis
opel_parts: "Opel",
vauxhall_parts: "Opel",
// Volvo/Polestar
volvo_parts: "Volvo",
polestar_parts: "Polestar",
};
// Display names for services that share a brand (multi-catalog brands)
export const SERVICE_DISPLAY_NAMES: Record<string, string> = {
// BMW Group
bmw_parts: "BMW",
bmwclassic_parts: "BMW Classic",
bmwmotorrad_parts: "BMW Motorrad",
bmwmotorradclassic_parts: "BMW Motorrad Classic",
mini_parts: "Mini",
miniclassic_parts: "Mini Classic",
// Mercedes-Benz Group
mercedes_parts: "Mercedes-Benz",
mercedesclassic_parts: "Mercedes-Benz Classic",
mercedesvans_parts: "Mercedes-Benz Vans",
mercedestrucks_parts: "Mercedes-Benz Trucks",
mercedesunimog_parts: "Mercedes-Benz Unimog",
// Volkswagen Group
vw_parts: "Volkswagen",
vwclassic_parts: "Volkswagen Classic",
vn_parts: "Volkswagen Nfz",
porsche_parts: "Porsche",
porscheclassic_parts: "Porsche Classic",
// Renault Group
renault_parts: "Renault",
dacia_parts: "Dacia",
alpine_parts: "Alpine",
// Ford
fordp_parts: "Ford",
fordt_parts: "Ford Ticari",
// Citroen
citroen_parts: "Citroen",
citroenDs_parts: "Citroen DS",
}; };

View File

@@ -31,6 +31,10 @@ export class PartsService {
if (!category) throw new NotFoundException("Kategori bulunamadı"); if (!category) throw new NotFoundException("Kategori bulunamadı");
if (!category.vehicleId) {
return dbParts;
}
const [vehicle] = await this.db const [vehicle] = await this.db
.select() .select()
.from(vehicles) .from(vehicles)
@@ -61,7 +65,7 @@ export class PartsService {
name: p.name, name: p.name,
nameOriginal: p.name, nameOriginal: p.name,
description: p.description || null, description: p.description || null,
quantity: p.quantity || null, quantity: p.quantity ? (parseInt(String(p.quantity), 10) || null) : null,
position: p.positionCode || null, position: p.positionCode || null,
hotspotIndex: p.hotspotId ? (() => { hotspotIndex: p.hotspotId ? (() => {
const val = parseInt(p.hotspotId!, 10); const val = parseInt(p.hotspotId!, 10);

View File

@@ -284,7 +284,7 @@ export class SubscriptionsService {
const now = new Date(); const now = new Date();
const endDate = new Date(now); const endDate = new Date(now);
endDate.setDate(endDate.getDate() + 3); endDate.setDate(endDate.getDate() + 7);
// Create trial subscription // Create trial subscription
const [subscription] = await this.db const [subscription] = await this.db

View File

@@ -165,13 +165,30 @@ export class VehiclesService {
/** /**
* Public VIN preview — no auth, no DB save, no brand access check. * Public VIN preview — no auth, no DB save, no brand access check.
* Uses resolveVin() which caches results in Redis for 5 minutes. * Checks DB first, then Redis, then external API chain.
*/ */
async previewVin(vin: string) { async previewVin(vin: string) {
if (!isValidVin(vin)) { if (!isValidVin(vin)) {
throw new BadRequestException("Geçersiz şase numarası"); throw new BadRequestException("Geçersiz şase numarası");
} }
// DB'de varsa direkt dön — dış API çağrısına gerek yok
const [existing] = await this.db
.select({
brandName: vehicles.brandName,
model: vehicles.model,
year: vehicles.year,
engine: vehicles.engine,
source: vehicles.source,
})
.from(vehicles)
.where(eq(vehicles.vin, vin))
.limit(1);
if (existing) {
return existing;
}
const resolved = await this.resolveVin(vin); const resolved = await this.resolveVin(vin);
if (!resolved) { if (!resolved) {
throw new BadRequestException("Şase numarası tanınamadı"); throw new BadRequestException("Şase numarası tanınamadı");
@@ -249,7 +266,7 @@ export class VehiclesService {
// 3. PL24 (if PC had multiple results, or PC failed entirely) // 3. PL24 (if PC had multiple results, or PC failed entirely)
let pl24Vehicle: any = null; let pl24Vehicle: any = null;
if (this.pl24Service.isSupported(vin)) { if (this.pl24Service.isDecodeable(vin)) {
try { try {
pl24Vehicle = await this.pl24Service.decodeVin(vin); pl24Vehicle = await this.pl24Service.decodeVin(vin);
if (!brandName && pl24Vehicle) { if (!brandName && pl24Vehicle) {

View File

@@ -0,0 +1,175 @@
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Button, Card, CardContent, CardHeader, CardTitle } from "@sase/ui";
import { Loader2 } from "lucide-react";
interface VariantItem {
code: string;
name: string;
}
interface FordModelConfig {
modelYears: VariantItem[];
engines: VariantItem[];
gearboxes: VariantItem[];
}
interface FordVariantSelectorProps {
vehicleId: string;
onSelect: (modelYear: string, engine: string, gearbox: string) => void;
}
export function FordVariantSelector({ vehicleId, onSelect }: FordVariantSelectorProps) {
const { t } = useTranslation();
const [selectedYear, setSelectedYear] = useState<string | null>(null);
const [selectedEngine, setSelectedEngine] = useState<string | null>(null);
const [selectedGearbox, setSelectedGearbox] = useState<string | null>(null);
const { data: config, isLoading } = useQuery<FordModelConfig>({
queryKey: ["ford-config", vehicleId],
queryFn: () => api.get<FordModelConfig>(`/catalog/vehicles/${vehicleId}/ford-config`),
enabled: !!vehicleId,
});
const modelYears = config?.modelYears ?? [];
const engines = config?.engines ?? [];
const gearboxes = config?.gearboxes ?? [];
const hasYears = modelYears.length > 0;
const hasEngines = engines.length > 0;
const hasGearboxes = gearboxes.length > 0;
const handleYearSelect = (code: string) => {
setSelectedYear(code);
setSelectedEngine(null);
setSelectedGearbox(null);
};
const handleEngineSelect = (code: string) => {
setSelectedEngine(code);
setSelectedGearbox(null);
};
const handleGearboxSelect = (code: string) => {
setSelectedGearbox(code);
};
const hasAny = hasYears || hasEngines || hasGearboxes;
const canProceed =
!hasAny || // No variants available — can always proceed
((!hasYears || !!selectedYear) &&
(!hasEngines || !!selectedEngine) &&
(!hasGearboxes || !!selectedGearbox));
const handleProceed = () => {
if (!canProceed) return;
// When no variants, use "_nor_" so hasVariant=true and variant selector is skipped
onSelect(selectedYear ?? "_nor_", selectedEngine ?? "_nor_", selectedGearbox ?? "_nor_");
};
return (
<Card>
<CardHeader>
<CardTitle className="text-base">{t("catalog.fordVariant.title")}</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
{isLoading ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" />
{t("catalog.fordVariant.loading")}
</div>
) : (
<>
{/* Model Year */}
{hasYears && (
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.fordVariant.modelYear")}</p>
<div className="flex flex-wrap gap-2">
{modelYears.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleYearSelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedYear === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
</div>
</div>
)}
{/* Engine — shown after year selected or if no years */}
{hasEngines && (!hasYears || selectedYear) && (
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.fordVariant.engine")}</p>
<div className="flex flex-wrap gap-2">
{engines.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleEngineSelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedEngine === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
</div>
</div>
)}
{/* Gearbox — shown after engine selected or if no engines */}
{hasGearboxes && (!hasYears || selectedYear) && (!hasEngines || selectedEngine) && (
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.fordVariant.gearbox")}</p>
<div className="flex flex-wrap gap-2">
{gearboxes.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleGearboxSelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedGearbox === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
</div>
</div>
)}
{/* No config available — allow skipping */}
{!hasYears && !hasEngines && !hasGearboxes && (
<p className="text-sm text-muted-foreground">{t("catalog.fordVariant.noConfig")}</p>
)}
{/* Proceed button — only enabled when all required dimensions are selected */}
<div className="flex gap-2">
<Button
onClick={handleProceed}
disabled={!canProceed}
className="w-full sm:w-auto"
>
{t("catalog.fordVariant.proceed")}
</Button>
</div>
</>
)}
</CardContent>
</Card>
);
}

View File

@@ -0,0 +1,209 @@
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Button, Card, CardContent, CardHeader, CardTitle } from "@sase/ui";
import { Loader2 } from "lucide-react";
interface VariantItem {
code: string;
name: string;
}
interface PsaVariantSelectorProps {
vehicleId: string;
onSelect: (body: string, engine: string, gearbox: string) => void;
}
export function PsaVariantSelector({ vehicleId, onSelect }: PsaVariantSelectorProps) {
const { t } = useTranslation();
const [selectedBody, setSelectedBody] = useState<string | null>(null);
const [selectedEngine, setSelectedEngine] = useState<string | null>(null);
const [selectedGearbox, setSelectedGearbox] = useState<string | null>(null);
const { data: bodies = [], isLoading: loadingBodies } = useQuery<VariantItem[]>({
queryKey: ["psa-bodies", vehicleId],
queryFn: () => api.get<VariantItem[]>(`/catalog/vehicles/${vehicleId}/psa-bodies`),
enabled: !!vehicleId,
});
const { data: engines = [], isLoading: loadingEngines } = useQuery<VariantItem[]>({
queryKey: ["psa-engines", vehicleId, selectedBody],
queryFn: () =>
api.get<VariantItem[]>(
`/catalog/vehicles/${vehicleId}/psa-engines?body=${encodeURIComponent(selectedBody!)}`,
),
enabled: !!vehicleId && !!selectedBody,
});
const { data: gearboxes = [], isLoading: loadingGearboxes } = useQuery<VariantItem[]>({
queryKey: ["psa-gearboxes", vehicleId, selectedBody, selectedEngine],
queryFn: () =>
api.get<VariantItem[]>(
`/catalog/vehicles/${vehicleId}/psa-gearboxes?body=${encodeURIComponent(selectedBody!)}&engine=${encodeURIComponent(selectedEngine!)}`,
),
enabled: !!vehicleId && !!selectedBody && !!selectedEngine,
});
const handleBodySelect = (code: string | "_all_") => {
if (code === "_all_") {
onSelect("_all_", "_all_", "_all_");
return;
}
setSelectedBody(code);
setSelectedEngine(null);
setSelectedGearbox(null);
};
const handleEngineSelect = (code: string | "_all_") => {
if (code === "_all_") {
onSelect(selectedBody!, "_all_", "_all_");
return;
}
setSelectedEngine(code);
setSelectedGearbox(null);
};
const handleGearboxSelect = (code: string | "_all_") => {
if (code === "_all_") {
onSelect(selectedBody!, selectedEngine!, "_all_");
return;
}
setSelectedGearbox(code);
};
const handleProceed = () => {
if (selectedBody && selectedEngine && selectedGearbox) {
onSelect(selectedBody, selectedEngine, selectedGearbox);
}
};
const canProceed = selectedBody && selectedEngine && selectedGearbox;
return (
<Card>
<CardHeader>
<CardTitle className="text-base">{t("catalog.psaVariant.title")}</CardTitle>
<p className="text-sm text-muted-foreground">{t("catalog.psaVariant.subtitle")}</p>
</CardHeader>
<CardContent className="space-y-6">
{/* Body Type */}
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.psaVariant.body")}</p>
{loadingBodies ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" />
{t("catalog.psaVariant.loading")}
</div>
) : (
<div className="flex flex-wrap gap-2">
{bodies.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleBodySelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedBody === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
<button
type="button"
onClick={() => handleBodySelect("_all_")}
className="rounded-md border border-dashed border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent"
>
{t("catalog.psaVariant.showAll")}
</button>
</div>
)}
</div>
{/* Engine */}
{selectedBody && (
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.psaVariant.engine")}</p>
{loadingEngines ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" />
{t("catalog.psaVariant.loading")}
</div>
) : (
<div className="flex flex-wrap gap-2">
{engines.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleEngineSelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedEngine === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
<button
type="button"
onClick={() => handleEngineSelect("_all_")}
className="rounded-md border border-dashed border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent"
>
{t("catalog.psaVariant.showAll")}
</button>
</div>
)}
</div>
)}
{/* Gearbox */}
{selectedBody && selectedEngine && (
<div className="space-y-2">
<p className="text-sm font-medium">{t("catalog.psaVariant.gearbox")}</p>
{loadingGearboxes ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" />
{t("catalog.psaVariant.loading")}
</div>
) : (
<div className="flex flex-wrap gap-2">
{gearboxes.map((item) => (
<button
key={item.code}
type="button"
onClick={() => handleGearboxSelect(item.code)}
className={`rounded-md border px-3 py-1.5 text-sm transition-colors ${
selectedGearbox === item.code
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-background hover:bg-accent"
}`}
>
{item.name}
</button>
))}
<button
type="button"
onClick={() => handleGearboxSelect("_all_")}
className="rounded-md border border-dashed border-border px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent"
>
{t("catalog.psaVariant.showAll")}
</button>
</div>
)}
</div>
)}
{/* Proceed button */}
{canProceed && (
<Button onClick={handleProceed} className="w-full sm:w-auto">
{t("catalog.psaVariant.proceed")}
</Button>
)}
</CardContent>
</Card>
);
}

View File

@@ -19,9 +19,13 @@ interface Category {
interface CategoryGridProps { interface CategoryGridProps {
categories: Category[]; categories: Category[];
vehicleId: string; vehicleId: string;
catalogMode?: boolean;
brandName?: string;
parentId?: string;
variantSearch?: { body?: string; engine?: string; gearbox?: string };
} }
export function CategoryGrid({ categories, vehicleId }: CategoryGridProps) { export function CategoryGrid({ categories, vehicleId, catalogMode, brandName, parentId, variantSearch }: CategoryGridProps) {
const [prefetchingIds, setPrefetchingIds] = useState<Set<string>>(new Set()); const [prefetchingIds, setPrefetchingIds] = useState<Set<string>>(new Set());
const [imageOverrides, setImageOverrides] = useState<Map<string, string>>(new Map()); const [imageOverrides, setImageOverrides] = useState<Map<string, string>>(new Map());
const prefetchedRef = useRef<Set<string>>(new Set()); const prefetchedRef = useRef<Set<string>>(new Set());
@@ -104,8 +108,13 @@ export function CategoryGrid({ categories, vehicleId }: CategoryGridProps) {
return ( return (
<Link <Link
key={category.id} key={category.id}
to="/dashboard/vehicles/$id/categories/$categoryId" to={catalogMode
params={{ id: vehicleId, categoryId: category.id }} ? "/dashboard/catalog/$brandName/$modelId/categories/$categoryId"
: "/dashboard/vehicles/$id/categories/$categoryId"}
params={catalogMode
? { brandName: brandName ?? vehicleId, modelId: vehicleId, categoryId: category.id }
: { id: vehicleId, categoryId: category.id }}
search={catalogMode && variantSearch ? variantSearch : undefined}
className={category.unavailable ? "opacity-40" : undefined} className={category.unavailable ? "opacity-40" : undefined}
> >
<CategoryCard <CategoryCard

View File

@@ -17,21 +17,43 @@ interface Category {
source?: string; source?: string;
} }
export function CategoryTree({ categories, vehicleId }: { categories: Category[]; vehicleId: string }) { export function CategoryTree({
categories,
vehicleId,
catalogMode,
brandName,
variantSearch,
}: {
categories: Category[];
vehicleId: string;
catalogMode?: boolean;
brandName?: string;
variantSearch?: { body?: string; engine?: string; gearbox?: string };
}) {
if (!categories || categories.length === 0) { if (!categories || categories.length === 0) {
return <p className="py-4 text-center text-sm text-muted-foreground">Kategori bulunamadi.</p>; return <p className="py-4 text-center text-sm text-muted-foreground">Kategori bulunamadi.</p>;
} }
return ( return (
<div className="space-y-1"> <div className="space-y-1">
{categories.map((cat) => ( {categories.map((cat) => (
<CategoryNode key={cat.id} category={cat} vehicleId={vehicleId} level={0} parentPrefetching={false} /> <CategoryNode
key={cat.id}
category={cat}
vehicleId={vehicleId}
level={0}
parentPrefetching={false}
catalogMode={catalogMode}
brandName={brandName}
variantSearch={variantSearch}
/>
))} ))}
</div> </div>
); );
} }
function CategoryNode({ category, vehicleId, level, parentPrefetching }: { function CategoryNode({ category, vehicleId, level, parentPrefetching, catalogMode, brandName, variantSearch }: {
category: Category; vehicleId: string; level: number; parentPrefetching: boolean; category: Category; vehicleId: string; level: number; parentPrefetching: boolean;
catalogMode?: boolean; brandName?: string; variantSearch?: { body?: string; engine?: string; gearbox?: string };
}) { }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
@@ -131,8 +153,14 @@ function CategoryNode({ category, vehicleId, level, parentPrefetching }: {
)} )}
<SchemaIcon Icon={Icon} schemaImageUrl={category.schemaImageUrl} name={category.name} shimmer={isShimmering} /> <SchemaIcon Icon={Icon} schemaImageUrl={category.schemaImageUrl} name={category.name} shimmer={isShimmering} />
{isLeaf ? ( {isLeaf ? (
<Link to="/dashboard/vehicles/$id/categories/$categoryId" <Link
params={{ id: vehicleId, categoryId: category.id }} to={catalogMode
? "/dashboard/catalog/$brandName/$modelId/categories/$categoryId"
: "/dashboard/vehicles/$id/categories/$categoryId"}
params={catalogMode
? { brandName: brandName ?? vehicleId, modelId: vehicleId, categoryId: category.id }
: { id: vehicleId, categoryId: category.id }}
search={catalogMode && variantSearch ? variantSearch : undefined}
className="flex-1 truncate hover:underline"> className="flex-1 truncate hover:underline">
{category.name} {category.name}
</Link> </Link>
@@ -150,7 +178,8 @@ function CategoryNode({ category, vehicleId, level, parentPrefetching }: {
<div> <div>
{children.map((child) => ( {children.map((child) => (
<CategoryNode key={child.id} category={child} vehicleId={vehicleId} <CategoryNode key={child.id} category={child} vehicleId={vehicleId}
level={level + 1} parentPrefetching={prefetching} /> level={level + 1} parentPrefetching={prefetching}
catalogMode={catalogMode} brandName={brandName} variantSearch={variantSearch} />
))} ))}
</div> </div>
)} )}

View File

@@ -30,12 +30,52 @@
"nav": { "nav": {
"search": "Search", "search": "Search",
"history": "History", "history": "History",
"catalog": "Catalog",
"subscription": "Subscription", "subscription": "Subscription",
"billing": "Billing", "billing": "Billing",
"settings": "Settings", "settings": "Settings",
"admin": "Admin Panel", "admin": "Admin Panel",
"logout": "Log Out" "logout": "Log Out"
}, },
"catalog": {
"title": "Parts Catalog",
"brands": "Brands",
"models": "Models",
"allBrands": "All Brands",
"modelCount": "{count} models",
"noBrands": "Catalog data is being prepared",
"noModels": "No models found",
"locked": "This brand is not in your plan",
"upgradeCta": "Upgrade Plan",
"loadingModels": "Loading models...",
"categories": "Categories",
"parts": "Parts",
"backToBrands": "Back to Brands",
"backToModels": "Back to Models",
"backToCategories": "Back to Categories",
"selectCatalog": "Select a catalog",
"psaVariant": {
"title": "Select Vehicle Variant",
"subtitle": "Optional — use Show All to browse all variants",
"body": "Body Type",
"engine": "Engine",
"gearbox": "Gearbox",
"showAll": "Show All",
"proceed": "Go to Catalog",
"loading": "Loading..."
},
"fordVariant": {
"title": "Select Model",
"subtitle": "Optional — use Show All to browse all variants",
"modelYear": "Model Year",
"engine": "Engine",
"gearbox": "Gearbox",
"showAll": "Show All",
"proceed": "Go to Catalog",
"loading": "Loading...",
"noConfig": "Variant info unavailable. You can still browse all categories."
}
},
"auth": { "auth": {
"login": "Log In", "login": "Log In",
"register": "Sign Up", "register": "Sign Up",
@@ -124,10 +164,10 @@
"expired": "Expired" "expired": "Expired"
}, },
"popular": "Popular", "popular": "Popular",
"trialTitle": "3-Day Full Package Trial", "trialTitle": "7-Day Full Package Trial",
"trialDescription": "Free access to all brands for 3 days. No credit card required.", "trialDescription": "Free access to all brands for 7 days. No credit card required.",
"startTrial": "Start Free Trial", "startTrial": "Start Free Trial",
"trialStarted": "Your 3-day Full Package trial has started!", "trialStarted": "Your 7-day Full Package trial has started!",
"onboarding": { "onboarding": {
"provisioning": "Setting up your free trial", "provisioning": "Setting up your free trial",
"step1": "Verifying account", "step1": "Verifying account",
@@ -135,7 +175,7 @@
"step3": "Activating Full Package", "step3": "Activating Full Package",
"step4": "Completed!", "step4": "Completed!",
"completed": "You can test all catalogs without limits!", "completed": "You can test all catalogs without limits!",
"trialDuration": "3-Day Trial", "trialDuration": "7-Day Trial",
"startSearching": "Start Searching", "startSearching": "Start Searching",
"error": "An error occurred while starting your trial.", "error": "An error occurred while starting your trial.",
"retry": "Try Again" "retry": "Try Again"

View File

@@ -30,12 +30,52 @@
"nav": { "nav": {
"search": "Arama", "search": "Arama",
"history": "Geçmiş", "history": "Geçmiş",
"catalog": "Katalog",
"subscription": "Abonelik", "subscription": "Abonelik",
"billing": "Fatura", "billing": "Fatura",
"settings": "Ayarlar", "settings": "Ayarlar",
"admin": "Admin Panel", "admin": "Admin Panel",
"logout": ıkış Yap" "logout": ıkış Yap"
}, },
"catalog": {
"title": "Parça Kataloğu",
"brands": "Markalar",
"models": "Modeller",
"allBrands": "Tüm Markalar",
"modelCount": "{count} model",
"noBrands": "Katalog verisi hazırlanıyor",
"noModels": "Model bulunamadı",
"locked": "Bu marka planınızda yok",
"upgradeCta": "Planını Yükselt",
"loadingModels": "Modeller yükleniyor...",
"categories": "Kategoriler",
"parts": "Parçalar",
"backToBrands": "Markalara Dön",
"backToModels": "Modellere Dön",
"backToCategories": "Kategorilere Dön",
"selectCatalog": "Bir katalog seçin",
"psaVariant": {
"title": "Araç Varyantını Seçin",
"subtitle": "İsteğe bağlı — tüm varyantlar için Tümü seçeneğini kullanın",
"body": "Kasa Tipi",
"engine": "Motor",
"gearbox": "Şanzıman",
"showAll": "Tümü",
"proceed": "Kataloga Git",
"loading": "Yükleniyor..."
},
"fordVariant": {
"title": "Model Seçin",
"subtitle": "İsteğe bağlı — tüm varyantlar için Tümü seçeneğini kullanın",
"modelYear": "Model Yılı",
"engine": "Motor",
"gearbox": "Şanzıman",
"showAll": "Tümü",
"proceed": "Kataloga Git",
"loading": "Yükleniyor...",
"noConfig": "Varyant bilgisi yüklenemedi. Tüm kategorilere göz atabilirsiniz."
}
},
"auth": { "auth": {
"login": "Giriş Yap", "login": "Giriş Yap",
"register": "Kayıt Ol", "register": "Kayıt Ol",
@@ -124,10 +164,10 @@
"expired": "Süresi Doldu" "expired": "Süresi Doldu"
}, },
"popular": "Popüler", "popular": "Popüler",
"trialTitle": "3 Gün Full Paket Denemesi", "trialTitle": "7 Gün Full Paket Denemesi",
"trialDescription": "Tüm markalara 3 gün boyunca ücretsiz erişim. Kredi kartı gerekmez.", "trialDescription": "Tüm markalara 7 gün boyunca ücretsiz erişim. Kredi kartı gerekmez.",
"startTrial": "Ücretsiz Denemeyi Başlat", "startTrial": "Ücretsiz Denemeyi Başlat",
"trialStarted": "3 günlük Full Paket denemeniz başlatıldı!", "trialStarted": "7 günlük Full Paket denemeniz başlatıldı!",
"onboarding": { "onboarding": {
"provisioning": "Ücretsiz kullanım hakkınız tanımlanıyor", "provisioning": "Ücretsiz kullanım hakkınız tanımlanıyor",
"step1": "Hesap doğrulanıyor", "step1": "Hesap doğrulanıyor",
@@ -135,7 +175,7 @@
"step3": "Full Paket aktif ediliyor", "step3": "Full Paket aktif ediliyor",
"step4": "Tamamlandı!", "step4": "Tamamlandı!",
"completed": "Tüm katalogları sınırsız test edebilirsiniz!", "completed": "Tüm katalogları sınırsız test edebilirsiniz!",
"trialDuration": "3 Gün Deneme", "trialDuration": "7 Gün Deneme",
"startSearching": "Şase Aramaya Başla", "startSearching": "Şase Aramaya Başla",
"error": "Deneme başlatılırken bir hata oluştu.", "error": "Deneme başlatılırken bir hata oluştu.",
"retry": "Tekrar Dene" "retry": "Tekrar Dene"

View File

@@ -31,6 +31,7 @@ import { Route as AuthRegisterRouteImport } from "./routes/_auth/register"
import { Route as AuthLoginRouteImport } from "./routes/_auth/login" import { Route as AuthLoginRouteImport } from "./routes/_auth/login"
import { Route as AuthForgotPasswordRouteImport } from "./routes/_auth/forgot-password" import { Route as AuthForgotPasswordRouteImport } from "./routes/_auth/forgot-password"
import { Route as DashboardSubscriptionIndexRouteImport } from "./routes/dashboard/subscription/index" import { Route as DashboardSubscriptionIndexRouteImport } from "./routes/dashboard/subscription/index"
import { Route as DashboardCatalogIndexRouteImport } from "./routes/dashboard/catalog/index"
import { Route as DashboardAdminIndexRouteImport } from "./routes/dashboard/admin/index" import { Route as DashboardAdminIndexRouteImport } from "./routes/dashboard/admin/index"
import { Route as DashboardSubscriptionPayRouteImport } from "./routes/dashboard/subscription/pay" import { Route as DashboardSubscriptionPayRouteImport } from "./routes/dashboard/subscription/pay"
import { Route as DashboardAdminUsersRouteImport } from "./routes/dashboard/admin/users" import { Route as DashboardAdminUsersRouteImport } from "./routes/dashboard/admin/users"
@@ -39,7 +40,10 @@ import { Route as DashboardAdminPaymentsRouteImport } from "./routes/dashboard/a
import { Route as DashboardAdminCopyLogsRouteImport } from "./routes/dashboard/admin/copy-logs" import { Route as DashboardAdminCopyLogsRouteImport } from "./routes/dashboard/admin/copy-logs"
import { Route as DashboardAdminAnalyticsRouteImport } from "./routes/dashboard/admin/analytics" import { Route as DashboardAdminAnalyticsRouteImport } from "./routes/dashboard/admin/analytics"
import { Route as DashboardVehiclesIdIndexRouteImport } from "./routes/dashboard/vehicles_/$id/index" import { Route as DashboardVehiclesIdIndexRouteImport } from "./routes/dashboard/vehicles_/$id/index"
import { Route as DashboardCatalogBrandNameIndexRouteImport } from "./routes/dashboard/catalog_/$brandName/index"
import { Route as DashboardCatalogBrandNameModelIdIndexRouteImport } from "./routes/dashboard/catalog_/$brandName_/$modelId/index"
import { Route as DashboardVehiclesIdCategoriesCategoryIdRouteImport } from "./routes/dashboard/vehicles_/$id/categories_/$categoryId" import { Route as DashboardVehiclesIdCategoriesCategoryIdRouteImport } from "./routes/dashboard/vehicles_/$id/categories_/$categoryId"
import { Route as DashboardCatalogBrandNameModelIdCategoriesCategoryIdRouteImport } from "./routes/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId"
const TermsRoute = TermsRouteImport.update({ const TermsRoute = TermsRouteImport.update({
id: "/terms", id: "/terms",
@@ -151,6 +155,11 @@ const DashboardSubscriptionIndexRoute =
path: "/subscription/", path: "/subscription/",
getParentRoute: () => DashboardRoute, getParentRoute: () => DashboardRoute,
} as any) } as any)
const DashboardCatalogIndexRoute = DashboardCatalogIndexRouteImport.update({
id: "/catalog/",
path: "/catalog/",
getParentRoute: () => DashboardRoute,
} as any)
const DashboardAdminIndexRoute = DashboardAdminIndexRouteImport.update({ const DashboardAdminIndexRoute = DashboardAdminIndexRouteImport.update({
id: "/admin/", id: "/admin/",
path: "/admin/", path: "/admin/",
@@ -193,12 +202,30 @@ const DashboardVehiclesIdIndexRoute =
path: "/vehicles/$id/", path: "/vehicles/$id/",
getParentRoute: () => DashboardRoute, getParentRoute: () => DashboardRoute,
} as any) } as any)
const DashboardCatalogBrandNameIndexRoute =
DashboardCatalogBrandNameIndexRouteImport.update({
id: "/catalog_/$brandName/",
path: "/catalog/$brandName/",
getParentRoute: () => DashboardRoute,
} as any)
const DashboardCatalogBrandNameModelIdIndexRoute =
DashboardCatalogBrandNameModelIdIndexRouteImport.update({
id: "/catalog_/$brandName_/$modelId/",
path: "/catalog/$brandName/$modelId/",
getParentRoute: () => DashboardRoute,
} as any)
const DashboardVehiclesIdCategoriesCategoryIdRoute = const DashboardVehiclesIdCategoriesCategoryIdRoute =
DashboardVehiclesIdCategoriesCategoryIdRouteImport.update({ DashboardVehiclesIdCategoriesCategoryIdRouteImport.update({
id: "/vehicles_/$id/categories_/$categoryId", id: "/vehicles_/$id/categories_/$categoryId",
path: "/vehicles/$id/categories/$categoryId", path: "/vehicles/$id/categories/$categoryId",
getParentRoute: () => DashboardRoute, getParentRoute: () => DashboardRoute,
} as any) } as any)
const DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute =
DashboardCatalogBrandNameModelIdCategoriesCategoryIdRouteImport.update({
id: "/catalog_/$brandName_/$modelId/categories_/$categoryId",
path: "/catalog/$brandName/$modelId/categories/$categoryId",
getParentRoute: () => DashboardRoute,
} as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
"/": typeof IndexRoute "/": typeof IndexRoute
@@ -228,9 +255,13 @@ export interface FileRoutesByFullPath {
"/dashboard/admin/users": typeof DashboardAdminUsersRoute "/dashboard/admin/users": typeof DashboardAdminUsersRoute
"/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute "/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute
"/dashboard/admin/": typeof DashboardAdminIndexRoute "/dashboard/admin/": typeof DashboardAdminIndexRoute
"/dashboard/catalog/": typeof DashboardCatalogIndexRoute
"/dashboard/subscription/": typeof DashboardSubscriptionIndexRoute "/dashboard/subscription/": typeof DashboardSubscriptionIndexRoute
"/dashboard/catalog/$brandName/": typeof DashboardCatalogBrandNameIndexRoute
"/dashboard/vehicles/$id/": typeof DashboardVehiclesIdIndexRoute "/dashboard/vehicles/$id/": typeof DashboardVehiclesIdIndexRoute
"/dashboard/vehicles/$id/categories/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute "/dashboard/vehicles/$id/categories/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute
"/dashboard/catalog/$brandName/$modelId/": typeof DashboardCatalogBrandNameModelIdIndexRoute
"/dashboard/catalog/$brandName/$modelId/categories/$categoryId": typeof DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
"/": typeof IndexRoute "/": typeof IndexRoute
@@ -259,9 +290,13 @@ export interface FileRoutesByTo {
"/dashboard/admin/users": typeof DashboardAdminUsersRoute "/dashboard/admin/users": typeof DashboardAdminUsersRoute
"/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute "/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute
"/dashboard/admin": typeof DashboardAdminIndexRoute "/dashboard/admin": typeof DashboardAdminIndexRoute
"/dashboard/catalog": typeof DashboardCatalogIndexRoute
"/dashboard/subscription": typeof DashboardSubscriptionIndexRoute "/dashboard/subscription": typeof DashboardSubscriptionIndexRoute
"/dashboard/catalog/$brandName": typeof DashboardCatalogBrandNameIndexRoute
"/dashboard/vehicles/$id": typeof DashboardVehiclesIdIndexRoute "/dashboard/vehicles/$id": typeof DashboardVehiclesIdIndexRoute
"/dashboard/vehicles/$id/categories/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute "/dashboard/vehicles/$id/categories/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute
"/dashboard/catalog/$brandName/$modelId": typeof DashboardCatalogBrandNameModelIdIndexRoute
"/dashboard/catalog/$brandName/$modelId/categories/$categoryId": typeof DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
@@ -293,9 +328,13 @@ export interface FileRoutesById {
"/dashboard/admin/users": typeof DashboardAdminUsersRoute "/dashboard/admin/users": typeof DashboardAdminUsersRoute
"/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute "/dashboard/subscription/pay": typeof DashboardSubscriptionPayRoute
"/dashboard/admin/": typeof DashboardAdminIndexRoute "/dashboard/admin/": typeof DashboardAdminIndexRoute
"/dashboard/catalog/": typeof DashboardCatalogIndexRoute
"/dashboard/subscription/": typeof DashboardSubscriptionIndexRoute "/dashboard/subscription/": typeof DashboardSubscriptionIndexRoute
"/dashboard/catalog_/$brandName/": typeof DashboardCatalogBrandNameIndexRoute
"/dashboard/vehicles_/$id/": typeof DashboardVehiclesIdIndexRoute "/dashboard/vehicles_/$id/": typeof DashboardVehiclesIdIndexRoute
"/dashboard/vehicles_/$id/categories_/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute "/dashboard/vehicles_/$id/categories_/$categoryId": typeof DashboardVehiclesIdCategoriesCategoryIdRoute
"/dashboard/catalog_/$brandName_/$modelId/": typeof DashboardCatalogBrandNameModelIdIndexRoute
"/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId": typeof DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
@@ -327,9 +366,13 @@ export interface FileRouteTypes {
| "/dashboard/admin/users" | "/dashboard/admin/users"
| "/dashboard/subscription/pay" | "/dashboard/subscription/pay"
| "/dashboard/admin/" | "/dashboard/admin/"
| "/dashboard/catalog/"
| "/dashboard/subscription/" | "/dashboard/subscription/"
| "/dashboard/catalog/$brandName/"
| "/dashboard/vehicles/$id/" | "/dashboard/vehicles/$id/"
| "/dashboard/vehicles/$id/categories/$categoryId" | "/dashboard/vehicles/$id/categories/$categoryId"
| "/dashboard/catalog/$brandName/$modelId/"
| "/dashboard/catalog/$brandName/$modelId/categories/$categoryId"
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: to:
| "/" | "/"
@@ -358,9 +401,13 @@ export interface FileRouteTypes {
| "/dashboard/admin/users" | "/dashboard/admin/users"
| "/dashboard/subscription/pay" | "/dashboard/subscription/pay"
| "/dashboard/admin" | "/dashboard/admin"
| "/dashboard/catalog"
| "/dashboard/subscription" | "/dashboard/subscription"
| "/dashboard/catalog/$brandName"
| "/dashboard/vehicles/$id" | "/dashboard/vehicles/$id"
| "/dashboard/vehicles/$id/categories/$categoryId" | "/dashboard/vehicles/$id/categories/$categoryId"
| "/dashboard/catalog/$brandName/$modelId"
| "/dashboard/catalog/$brandName/$modelId/categories/$categoryId"
id: id:
| "__root__" | "__root__"
| "/" | "/"
@@ -391,9 +438,13 @@ export interface FileRouteTypes {
| "/dashboard/admin/users" | "/dashboard/admin/users"
| "/dashboard/subscription/pay" | "/dashboard/subscription/pay"
| "/dashboard/admin/" | "/dashboard/admin/"
| "/dashboard/catalog/"
| "/dashboard/subscription/" | "/dashboard/subscription/"
| "/dashboard/catalog_/$brandName/"
| "/dashboard/vehicles_/$id/" | "/dashboard/vehicles_/$id/"
| "/dashboard/vehicles_/$id/categories_/$categoryId" | "/dashboard/vehicles_/$id/categories_/$categoryId"
| "/dashboard/catalog_/$brandName_/$modelId/"
| "/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId"
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
@@ -567,6 +618,13 @@ declare module "@tanstack/react-router" {
preLoaderRoute: typeof DashboardSubscriptionIndexRouteImport preLoaderRoute: typeof DashboardSubscriptionIndexRouteImport
parentRoute: typeof DashboardRoute parentRoute: typeof DashboardRoute
} }
"/dashboard/catalog/": {
id: "/dashboard/catalog/"
path: "/catalog"
fullPath: "/dashboard/catalog/"
preLoaderRoute: typeof DashboardCatalogIndexRouteImport
parentRoute: typeof DashboardRoute
}
"/dashboard/admin/": { "/dashboard/admin/": {
id: "/dashboard/admin/" id: "/dashboard/admin/"
path: "/admin" path: "/admin"
@@ -623,6 +681,20 @@ declare module "@tanstack/react-router" {
preLoaderRoute: typeof DashboardVehiclesIdIndexRouteImport preLoaderRoute: typeof DashboardVehiclesIdIndexRouteImport
parentRoute: typeof DashboardRoute parentRoute: typeof DashboardRoute
} }
"/dashboard/catalog_/$brandName/": {
id: "/dashboard/catalog_/$brandName/"
path: "/catalog/$brandName"
fullPath: "/dashboard/catalog/$brandName/"
preLoaderRoute: typeof DashboardCatalogBrandNameIndexRouteImport
parentRoute: typeof DashboardRoute
}
"/dashboard/catalog_/$brandName_/$modelId/": {
id: "/dashboard/catalog_/$brandName_/$modelId/"
path: "/catalog/$brandName/$modelId"
fullPath: "/dashboard/catalog/$brandName/$modelId/"
preLoaderRoute: typeof DashboardCatalogBrandNameModelIdIndexRouteImport
parentRoute: typeof DashboardRoute
}
"/dashboard/vehicles_/$id/categories_/$categoryId": { "/dashboard/vehicles_/$id/categories_/$categoryId": {
id: "/dashboard/vehicles_/$id/categories_/$categoryId" id: "/dashboard/vehicles_/$id/categories_/$categoryId"
path: "/vehicles/$id/categories/$categoryId" path: "/vehicles/$id/categories/$categoryId"
@@ -630,6 +702,13 @@ declare module "@tanstack/react-router" {
preLoaderRoute: typeof DashboardVehiclesIdCategoriesCategoryIdRouteImport preLoaderRoute: typeof DashboardVehiclesIdCategoriesCategoryIdRouteImport
parentRoute: typeof DashboardRoute parentRoute: typeof DashboardRoute
} }
"/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId": {
id: "/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId"
path: "/catalog/$brandName/$modelId/categories/$categoryId"
fullPath: "/dashboard/catalog/$brandName/$modelId/categories/$categoryId"
preLoaderRoute: typeof DashboardCatalogBrandNameModelIdCategoriesCategoryIdRouteImport
parentRoute: typeof DashboardRoute
}
} }
} }
@@ -662,9 +741,13 @@ interface DashboardRouteChildren {
DashboardAdminUsersRoute: typeof DashboardAdminUsersRoute DashboardAdminUsersRoute: typeof DashboardAdminUsersRoute
DashboardSubscriptionPayRoute: typeof DashboardSubscriptionPayRoute DashboardSubscriptionPayRoute: typeof DashboardSubscriptionPayRoute
DashboardAdminIndexRoute: typeof DashboardAdminIndexRoute DashboardAdminIndexRoute: typeof DashboardAdminIndexRoute
DashboardCatalogIndexRoute: typeof DashboardCatalogIndexRoute
DashboardSubscriptionIndexRoute: typeof DashboardSubscriptionIndexRoute DashboardSubscriptionIndexRoute: typeof DashboardSubscriptionIndexRoute
DashboardCatalogBrandNameIndexRoute: typeof DashboardCatalogBrandNameIndexRoute
DashboardVehiclesIdIndexRoute: typeof DashboardVehiclesIdIndexRoute DashboardVehiclesIdIndexRoute: typeof DashboardVehiclesIdIndexRoute
DashboardVehiclesIdCategoriesCategoryIdRoute: typeof DashboardVehiclesIdCategoriesCategoryIdRoute DashboardVehiclesIdCategoriesCategoryIdRoute: typeof DashboardVehiclesIdCategoriesCategoryIdRoute
DashboardCatalogBrandNameModelIdIndexRoute: typeof DashboardCatalogBrandNameModelIdIndexRoute
DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute: typeof DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute
} }
const DashboardRouteChildren: DashboardRouteChildren = { const DashboardRouteChildren: DashboardRouteChildren = {
@@ -680,10 +763,16 @@ const DashboardRouteChildren: DashboardRouteChildren = {
DashboardAdminUsersRoute: DashboardAdminUsersRoute, DashboardAdminUsersRoute: DashboardAdminUsersRoute,
DashboardSubscriptionPayRoute: DashboardSubscriptionPayRoute, DashboardSubscriptionPayRoute: DashboardSubscriptionPayRoute,
DashboardAdminIndexRoute: DashboardAdminIndexRoute, DashboardAdminIndexRoute: DashboardAdminIndexRoute,
DashboardCatalogIndexRoute: DashboardCatalogIndexRoute,
DashboardSubscriptionIndexRoute: DashboardSubscriptionIndexRoute, DashboardSubscriptionIndexRoute: DashboardSubscriptionIndexRoute,
DashboardCatalogBrandNameIndexRoute: DashboardCatalogBrandNameIndexRoute,
DashboardVehiclesIdIndexRoute: DashboardVehiclesIdIndexRoute, DashboardVehiclesIdIndexRoute: DashboardVehiclesIdIndexRoute,
DashboardVehiclesIdCategoriesCategoryIdRoute: DashboardVehiclesIdCategoriesCategoryIdRoute:
DashboardVehiclesIdCategoriesCategoryIdRoute, DashboardVehiclesIdCategoriesCategoryIdRoute,
DashboardCatalogBrandNameModelIdIndexRoute:
DashboardCatalogBrandNameModelIdIndexRoute,
DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute:
DashboardCatalogBrandNameModelIdCategoriesCategoryIdRoute,
} }
const DashboardRouteWithChildren = DashboardRoute._addFileChildren( const DashboardRouteWithChildren = DashboardRoute._addFileChildren(

View File

@@ -102,7 +102,7 @@ function AuthLayout() {
{/* Bottom trial badge */} {/* Bottom trial badge */}
<div className="flex items-center gap-2 pt-6 text-sm text-neutral-400"> <div className="flex items-center gap-2 pt-6 text-sm text-neutral-400">
<ShieldCheck className="size-4" /> <ShieldCheck className="size-4" />
3 gün Full Paket ücretsiz deneyin kredi kartı gerekmez 7 gün Full Paket ücretsiz deneyin kredi kartı gerekmez
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Link, createFileRoute, useNavigate } from "@tanstack/react-router"; import { Link, createFileRoute } from "@tanstack/react-router";
import { Button } from "@sase/ui"; import { Button } from "@sase/ui";
import { Input } from "@sase/ui"; import { Input } from "@sase/ui";
import { Label } from "@sase/ui"; import { Label } from "@sase/ui";
@@ -14,7 +14,6 @@ export const Route = createFileRoute("/_auth/login")({
}); });
function LoginPage() { function LoginPage() {
const navigate = useNavigate();
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -41,7 +40,7 @@ function LoginPage() {
} }
} else { } else {
capture("user_logged_in", { method: "email" }); capture("user_logged_in", { method: "email" });
navigate({ to: "/dashboard/search" }); window.location.href = "/dashboard/search";
} }
setLoading(false); setLoading(false);

View File

@@ -69,7 +69,7 @@ function RegisterPage() {
{/* Trial messaging */} {/* Trial messaging */}
<div className="mt-3 flex items-center gap-2 rounded-lg bg-emerald-500/10 px-3 py-2 text-sm text-emerald-600 dark:text-emerald-400"> <div className="mt-3 flex items-center gap-2 rounded-lg bg-emerald-500/10 px-3 py-2 text-sm text-emerald-600 dark:text-emerald-400">
<ShieldCheck className="size-4 shrink-0" /> <ShieldCheck className="size-4 shrink-0" />
3 gün Full Paket ücretsiz deneyin kredi kartı gerekmez 7 gün Full Paket ücretsiz deneyin kredi kartı gerekmez
</div> </div>
</div> </div>

View File

@@ -26,6 +26,7 @@ import {
Sun, Sun,
Moon, Moon,
Copy, Copy,
Library,
} from "lucide-react"; } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { getUserSettings, setUserSetting } from "@/lib/user-settings"; import { getUserSettings, setUserSetting } from "@/lib/user-settings";
@@ -40,6 +41,7 @@ export const Route = createFileRoute("/dashboard")({
const mainMenuItems = [ const mainMenuItems = [
{ to: "/dashboard", label: "Gösterge Paneli", icon: LayoutDashboard, exact: true }, { to: "/dashboard", label: "Gösterge Paneli", icon: LayoutDashboard, exact: true },
{ to: "/dashboard/search", label: "nav.search", translatable: true, icon: Search }, { to: "/dashboard/search", label: "nav.search", translatable: true, icon: Search },
{ to: "/dashboard/catalog", label: "nav.catalog", translatable: true, icon: Library },
{ to: "/dashboard/history", label: "nav.history", translatable: true, icon: History }, { to: "/dashboard/history", label: "nav.history", translatable: true, icon: History },
] as const; ] as const;

View File

@@ -0,0 +1,97 @@
import { createFileRoute, Link } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Skeleton } from "@sase/ui";
import { Library, Lock } from "lucide-react";
export const Route = createFileRoute("/dashboard/catalog/")({
component: CatalogBrandsPage,
});
interface CatalogBrand {
brandName: string;
brandId: string | null;
logoUrl: string | null;
serviceNames: string[];
hasAccess: boolean;
}
function CatalogBrandsPage() {
const { t } = useTranslation();
const { data: brands, isLoading } = useQuery({
queryKey: ["catalog-brands"],
queryFn: () => api.get<CatalogBrand[]>("/catalog/brands"),
});
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold">{t("catalog.title")}</h1>
<p className="text-sm text-muted-foreground">{t("catalog.brands")}</p>
</div>
{isLoading ? (
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
{Array.from({ length: 10 }).map((_, i) => (
<Skeleton key={`brand-skel-${i}`} className="h-28 w-full rounded-xl" />
))}
</div>
) : !brands || brands.length === 0 ? (
<div className="flex flex-col items-center justify-center py-16 text-center">
<Library className="mb-4 size-12 text-muted-foreground/40" />
<p className="text-muted-foreground">{t("catalog.noBrands")}</p>
</div>
) : (
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
{brands.map((brand) => (
<BrandCard key={brand.brandName} brand={brand} />
))}
</div>
)}
</div>
);
}
function BrandCard({ brand }: { brand: CatalogBrand }) {
const { t } = useTranslation();
if (!brand.hasAccess) {
return (
<div className="relative flex flex-col items-center justify-center rounded-xl border border-border/50 bg-muted/30 p-4 text-center opacity-60 select-none">
<Lock className="mb-2 size-5 text-muted-foreground" />
<p className="text-sm font-semibold text-foreground">{brand.brandName}</p>
<p className="mt-1 text-xs text-muted-foreground">{t("catalog.locked")}</p>
<Link
to="/dashboard/subscription"
className="mt-2 text-xs font-medium text-primary hover:underline"
>
{t("catalog.upgradeCta")}
</Link>
</div>
);
}
return (
<Link
to="/dashboard/catalog/$brandName"
params={{ brandName: encodeURIComponent(brand.brandName) }}
search={{ catalog: undefined }}
className="flex flex-col items-center justify-center rounded-xl border border-border bg-card p-4 text-center transition-colors hover:bg-accent hover:border-accent-foreground/20"
>
{brand.logoUrl ? (
<img
src={brand.logoUrl}
alt={brand.brandName}
className="mb-2 h-10 w-auto object-contain"
/>
) : (
<div className="mb-2 flex size-10 items-center justify-center rounded-full bg-primary/10">
<Library className="size-5 text-primary" />
</div>
)}
<p className="text-sm font-semibold">{brand.brandName}</p>
</Link>
);
}

View File

@@ -0,0 +1,211 @@
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Button, Skeleton } from "@sase/ui";
import { ArrowLeft, BookOpen, Car, ChevronRight, Loader2 } from "lucide-react";
export const Route = createFileRoute("/dashboard/catalog_/$brandName/")({
validateSearch: (search: Record<string, unknown>) => ({
catalog: typeof search.catalog === "string" ? search.catalog : undefined,
}),
component: CatalogModelsPage,
});
interface CatalogEntry {
serviceName: string;
displayName: string;
}
interface CatalogVehicle {
id: string;
serviceName: string;
brandName: string;
model: string;
year: string | null;
engine: string | null;
bodyType: string | null;
transmission: string | null;
architecture: string | null;
}
function CatalogModelsPage() {
const { brandName } = Route.useParams();
const { catalog: activeCatalog } = Route.useSearch();
const { t } = useTranslation();
const navigate = useNavigate();
const decodedBrandName = decodeURIComponent(brandName);
// Always fetch catalogs to know whether this brand has multiple sub-catalogs
const { data: catalogs, isLoading: catalogsLoading } = useQuery({
queryKey: ["catalog-catalogs", decodedBrandName],
queryFn: () =>
api.get<CatalogEntry[]>(`/catalog/brands/${encodeURIComponent(decodedBrandName)}/catalogs`),
staleTime: 1000 * 60 * 30, // 30 min
});
const isMultiCatalog = (catalogs?.length ?? 0) > 1;
// Show models when: single-service brand, OR user has selected a sub-catalog
const shouldShowModels = !isMultiCatalog || !!activeCatalog;
const activeCatalogLabel = activeCatalog
? (catalogs?.find((c) => c.serviceName === activeCatalog)?.displayName ?? activeCatalog)
: null;
const { data: models, isLoading: modelsLoading } = useQuery({
queryKey: ["catalog-models", decodedBrandName, activeCatalog ?? null],
queryFn: () => {
const serviceParam = activeCatalog ? `?service=${encodeURIComponent(activeCatalog)}` : "";
return api.get<CatalogVehicle[]>(
`/catalog/brands/${encodeURIComponent(decodedBrandName)}/models${serviceParam}`,
);
},
enabled: shouldShowModels && !catalogsLoading,
});
const handleBack = () => {
if (isMultiCatalog && activeCatalog) {
// Go back to catalog selector
navigate({ to: ".", search: { catalog: undefined } });
} else {
navigate({ to: "/dashboard/catalog" });
}
};
return (
<div className="space-y-6">
{/* Breadcrumb */}
<div className="flex items-center gap-3">
<Button variant="ghost" size="icon" onClick={handleBack}>
<ArrowLeft className="size-4" />
</Button>
<div>
<div className="text-xs text-muted-foreground">
<Link to="/dashboard/catalog" className="hover:underline">
{t("catalog.title")}
</Link>
{" / "}
{isMultiCatalog && activeCatalog ? (
<>
<Link
to="."
search={{ catalog: undefined }}
className="hover:underline"
>
{decodedBrandName}
</Link>
{" / "}
<span className="font-medium text-foreground">{activeCatalogLabel}</span>
</>
) : (
<span className="font-medium text-foreground">{decodedBrandName}</span>
)}
</div>
<h1 className="text-xl font-bold">
{isMultiCatalog && activeCatalog ? activeCatalogLabel : decodedBrandName}
</h1>
</div>
</div>
{catalogsLoading ? (
<div className="grid grid-cols-2 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 4 }).map((_, i) => (
<Skeleton key={`cat-skel-${i}`} className="h-24 w-full rounded-xl" />
))}
</div>
) : isMultiCatalog && !activeCatalog ? (
// Sub-catalog selector
<CatalogSelector
catalogs={catalogs!}
brandName={brandName}
brandLabel={decodedBrandName}
/>
) : modelsLoading ? (
<div>
<div className="mb-4 flex items-center gap-2 text-sm text-muted-foreground">
<Loader2 className="size-4 animate-spin" />
{t("catalog.loadingModels")}
</div>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 9 }).map((_, i) => (
<Skeleton key={`model-skel-${i}`} className="h-24 w-full rounded-lg" />
))}
</div>
</div>
) : !models || models.length === 0 ? (
<div className="flex flex-col items-center justify-center py-16 text-center">
<Car className="mb-4 size-12 text-muted-foreground/40" />
<p className="text-muted-foreground">{t("catalog.noModels")}</p>
</div>
) : (
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
{models.map((model) => (
<ModelCard key={model.id} model={model} brandName={brandName} />
))}
</div>
)}
</div>
);
}
function CatalogSelector({
catalogs,
brandName,
brandLabel,
}: {
catalogs: CatalogEntry[];
brandName: string;
brandLabel: string;
}) {
const { t } = useTranslation();
return (
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
{t("catalog.selectCatalog")} {brandLabel}
</p>
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
{catalogs.map((cat) => (
<Link
key={cat.serviceName}
to="/dashboard/catalog/$brandName"
params={{ brandName }}
search={{ catalog: cat.serviceName }}
className="flex items-center justify-between rounded-xl border border-border bg-card p-5 transition-colors hover:bg-accent hover:border-accent-foreground/20"
>
<div className="flex items-center gap-3">
<div className="flex size-10 items-center justify-center rounded-full bg-primary/10">
<BookOpen className="size-5 text-primary" />
</div>
<div>
<p className="font-semibold">{cat.displayName}</p>
<p className="text-xs text-muted-foreground">{cat.serviceName}</p>
</div>
</div>
<ChevronRight className="size-4 text-muted-foreground" />
</Link>
))}
</div>
</div>
);
}
function ModelCard({ model, brandName }: { model: CatalogVehicle; brandName: string }) {
return (
<Link
to="/dashboard/catalog/$brandName/$modelId"
params={{ brandName, modelId: model.id }}
search={{ body: undefined, engine: undefined, gearbox: undefined }}
className="flex flex-col rounded-lg border border-border bg-card p-4 transition-colors hover:bg-accent hover:border-accent-foreground/20"
>
<p className="font-semibold">{model.model}</p>
<div className="mt-1.5 flex flex-wrap gap-x-3 gap-y-0.5 text-xs text-muted-foreground">
{model.year && <span>{model.year}</span>}
{model.engine && <span>{model.engine}</span>}
{model.bodyType && <span>{model.bodyType}</span>}
{model.transmission && <span>{model.transmission}</span>}
</div>
</Link>
);
}

View File

@@ -0,0 +1,152 @@
import { lazy, Suspense } from "react";
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Button, Skeleton } from "@sase/ui";
import { ArrowLeft } from "lucide-react";
import { CategoryGrid } from "@/components/categories/category-grid";
const SchemaViewer = lazy(() =>
import("@/components/schema/schema-viewer").then((mod) => ({
default: mod.SchemaViewer,
})),
);
function SchemaViewerFallback() {
return (
<div className="flex flex-col gap-4 rounded-lg border border-border md:h-[600px] md:flex-row">
<div className="flex h-[300px] items-center justify-center md:h-auto md:w-[60%]">
<Skeleton className="h-[80%] w-[80%]" />
</div>
<div className="w-full space-y-3 p-4 md:w-[40%]">
<Skeleton className="h-6 w-1/2" />
{Array.from({ length: 8 }).map((_, i) => (
<Skeleton key={`schema-skel-${i}`} className="h-10 w-full" />
))}
</div>
</div>
);
}
export const Route = createFileRoute(
"/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId",
)({
validateSearch: (search) => ({
body: typeof search.body === "string" ? search.body : undefined,
engine: typeof search.engine === "string" ? search.engine : undefined,
gearbox: typeof search.gearbox === "string" ? search.gearbox : undefined,
}),
component: CatalogCategoryPage,
});
function buildVariantQuery(body?: string, engine?: string, gearbox?: string): string {
const params = new URLSearchParams();
if (body) params.set("body", body);
if (engine) params.set("engine", engine);
if (gearbox) params.set("gearbox", gearbox);
const qs = params.toString();
return qs ? `?${qs}` : "";
}
function CatalogCategoryPage() {
const { brandName, modelId, categoryId } = Route.useParams();
const search = Route.useSearch();
const { t } = useTranslation();
const navigate = useNavigate();
const body = search.body;
const engine = search.engine;
const gearbox = search.gearbox;
const variantSearch = body || engine || gearbox ? { body, engine, gearbox } : undefined;
const { data, isLoading, error } = useQuery({
queryKey: ["catalog-category", modelId, categoryId, body, engine, gearbox],
queryFn: () =>
api.get<any>(
`/catalog/vehicles/${modelId}/categories/${categoryId}${buildVariantQuery(body, engine, gearbox)}`,
),
enabled: !!modelId && !!categoryId,
});
const hasChildren = data?.children && data.children.length > 0;
const handleBack = () => {
if (data?.parentId) {
navigate({
to: "/dashboard/catalog/$brandName/$modelId/categories/$categoryId",
params: { brandName, modelId, categoryId: data.parentId },
search: variantSearch ?? { body: undefined, engine: undefined, gearbox: undefined },
});
} else {
navigate({
to: "/dashboard/catalog/$brandName/$modelId",
params: { brandName, modelId },
search: variantSearch ?? { body: undefined, engine: undefined, gearbox: undefined },
});
}
};
if (isLoading) {
return (
<div className="space-y-4">
<Skeleton className="h-8 w-48" />
<SchemaViewerFallback />
</div>
);
}
if (error) {
return (
<div className="flex flex-col items-center justify-center py-16 text-center">
<p className="text-muted-foreground">{t("errors.generic")}</p>
<Button variant="ghost" className="mt-4" onClick={handleBack}>
{t("catalog.backToCategories")}
</Button>
</div>
);
}
return (
<div className="space-y-4">
{/* Header */}
<div className="flex items-center gap-3">
<Button variant="ghost" size="icon" onClick={handleBack} title={t("common.back")}>
<ArrowLeft className="size-4" />
</Button>
<div>
<div className="text-xs text-muted-foreground">
<Link to="/dashboard/catalog" className="hover:underline">
{t("catalog.title")}
</Link>
</div>
<h1 className="text-xl font-bold">{data?.name || t("catalog.categories")}</h1>
</div>
</div>
{/* Content */}
{hasChildren ? (
<CategoryGrid
categories={data.children}
vehicleId={modelId}
catalogMode
brandName={brandName}
parentId={categoryId}
variantSearch={variantSearch}
/>
) : (
<Suspense fallback={<SchemaViewerFallback />}>
<SchemaViewer
schemaPic={data?.schemaPics?.[0] ?? null}
hotspots={data?.hotspots ?? []}
parts={data?.parts ?? []}
isLoading={isLoading}
vehicleId={modelId}
categoryId={categoryId}
/>
</Suspense>
)}
</div>
);
}

View File

@@ -0,0 +1,251 @@
import { useState } from "react";
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api-client";
import { useTranslation } from "@/lib/i18n";
import { Button, Skeleton, Card, CardContent, CardHeader, CardTitle } from "@sase/ui";
import { ArrowLeft, LayoutGrid, List } from "lucide-react";
import { CategoryGrid } from "@/components/categories/category-grid";
import { CategoryTree } from "@/components/categories/category-tree";
import { PsaVariantSelector } from "@/components/catalog/psa-variant-selector";
import { FordVariantSelector } from "@/components/catalog/ford-variant-selector";
import { getUserSettings, setUserSetting } from "@/lib/user-settings";
export const Route = createFileRoute("/dashboard/catalog_/$brandName_/$modelId/")({
validateSearch: (search) => ({
body: typeof search.body === "string" ? search.body : undefined,
engine: typeof search.engine === "string" ? search.engine : undefined,
gearbox: typeof search.gearbox === "string" ? search.gearbox : undefined,
}),
component: CatalogVehiclePage,
});
function buildVariantQuery(body?: string, engine?: string, gearbox?: string): string {
const params = new URLSearchParams();
if (body) params.set("body", body);
if (engine) params.set("engine", engine);
if (gearbox) params.set("gearbox", gearbox);
const qs = params.toString();
return qs ? `?${qs}` : "";
}
function CatalogVehiclePage() {
const { brandName, modelId } = Route.useParams();
const search = Route.useSearch();
const { t } = useTranslation();
const navigate = useNavigate();
const body = search.body;
const engine = search.engine;
const gearbox = search.gearbox;
const hasVariant = !!(body || engine || gearbox);
const [viewMode, setViewMode] = useState<"grid" | "tree">(
() => getUserSettings().categoryViewMode ?? "grid",
);
const decodedBrandName = decodeURIComponent(brandName);
const changeViewMode = (mode: "grid" | "tree") => {
setViewMode(mode);
setUserSetting("categoryViewMode", mode);
};
const { data: vehicle, isLoading: vehicleLoading } = useQuery({
queryKey: ["catalog-vehicle", modelId],
queryFn: () => api.get<any>(`/catalog/vehicles/${modelId}`),
enabled: !!modelId,
});
const isPsa = vehicle?.architecture === "LEGACY_PSA";
const isP4Legacy = [
"LEGACY_FORD",
"LEGACY_VOLVO",
].includes(vehicle?.architecture);
const showPsaVariantSelector = isPsa && !hasVariant;
const showFordVariantSelector = isP4Legacy && !hasVariant;
const showVariantSelector = showPsaVariantSelector || showFordVariantSelector;
const variantSearch = hasVariant ? { body, engine, gearbox } : undefined;
const { data: categoryTree, isLoading: categoriesLoading } = useQuery({
queryKey: ["catalog-category-tree", modelId, body, engine, gearbox],
queryFn: () =>
api.get<any[]>(`/catalog/vehicles/${modelId}/categories${buildVariantQuery(body, engine, gearbox)}`),
enabled: !!modelId && !vehicleLoading && !showVariantSelector,
});
const handleVariantSelect = (selectedBody: string, selectedEngine: string, selectedGearbox: string) => {
const norm = (v: string) => (v && v !== "_all_" && v !== "_nor_" ? v : undefined);
navigate({
to: "/dashboard/catalog/$brandName/$modelId",
params: { brandName, modelId },
search: {
// For Ford (catCode) / Volvo (year) variants: keep the meaningful selection,
// strip _all_ / _nor_ (no-restriction) values to keep URL clean.
// Special case: if ALL are _nor_, pass body="_nor_" so hasVariant=true skips re-showing selector.
body: norm(selectedBody) ?? (selectedBody === "_nor_" ? "_nor_" : undefined),
engine: norm(selectedEngine),
gearbox: norm(selectedGearbox),
},
});
};
if (vehicleLoading) {
return (
<div className="mx-auto max-w-4xl space-y-6">
<Skeleton className="h-8 w-64" />
<Skeleton className="h-64 w-full" />
</div>
);
}
return (
<div className="mx-auto max-w-4xl space-y-6">
{/* Header / Breadcrumb */}
<div className="flex items-center gap-3">
<Button
variant="ghost"
size="icon"
onClick={() =>
navigate({
to: "/dashboard/catalog/$brandName",
params: { brandName },
search: { catalog: undefined },
})
}
>
<ArrowLeft className="size-4" />
</Button>
<div>
<div className="text-xs text-muted-foreground">
<Link to="/dashboard/catalog" className="hover:underline">
{t("catalog.title")}
</Link>
{" / "}
<Link
to="/dashboard/catalog/$brandName"
params={{ brandName }}
search={{ catalog: undefined }}
className="hover:underline"
>
{decodedBrandName}
</Link>
{" / "}
<span className="font-medium text-foreground">
{vehicle?.model}
</span>
{hasVariant && (
<>
{body && body !== "_all_" && (
<><span className="mx-1">/</span><span className="font-medium text-foreground">{body}</span></>
)}
{engine && engine !== "_all_" && (
<><span className="mx-1">/</span><span className="font-medium text-foreground">{engine}</span></>
)}
{gearbox && gearbox !== "_all_" && (
<><span className="mx-1">/</span><span className="font-medium text-foreground">{gearbox}</span></>
)}
</>
)}
</div>
<h1 className="text-xl font-bold">
{vehicle?.model}
{vehicle?.year && <span className="ml-2 text-base font-normal text-muted-foreground">({vehicle.year})</span>}
</h1>
</div>
</div>
{/* Vehicle Info */}
{vehicle && (
<Card>
<CardHeader>
<CardTitle className="text-base">{t("catalog.models")}</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-3 text-sm sm:grid-cols-3">
{vehicle.engine && (
<div>
<span className="text-muted-foreground">Motor:</span>{" "}
<span className="font-medium">{vehicle.engine}</span>
</div>
)}
{vehicle.bodyType && (
<div>
<span className="text-muted-foreground">Kasa:</span>{" "}
<span className="font-medium">{vehicle.bodyType}</span>
</div>
)}
{vehicle.transmission && (
<div>
<span className="text-muted-foreground">Vites:</span>{" "}
<span className="font-medium">{vehicle.transmission}</span>
</div>
)}
{vehicle.market && (
<div>
<span className="text-muted-foreground">Pazar:</span>{" "}
<span className="font-medium">{vehicle.market}</span>
</div>
)}
</div>
</CardContent>
</Card>
)}
{/* Variant Selector OR Categories */}
{showPsaVariantSelector ? (
<PsaVariantSelector vehicleId={modelId} onSelect={handleVariantSelect} />
) : showFordVariantSelector ? (
<FordVariantSelector vehicleId={modelId} onSelect={handleVariantSelect} />
) : (
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle className="text-base">{t("catalog.categories")}</CardTitle>
<div className="flex items-center gap-1">
<button
type="button"
onClick={() => changeViewMode("grid")}
className={`rounded p-1.5 ${viewMode === "grid" ? "bg-accent" : "text-muted-foreground hover:text-foreground"}`}
>
<LayoutGrid className="size-4" />
</button>
<button
type="button"
onClick={() => changeViewMode("tree")}
className={`rounded p-1.5 ${viewMode === "tree" ? "bg-accent" : "text-muted-foreground hover:text-foreground"}`}
>
<List className="size-4" />
</button>
</div>
</CardHeader>
<CardContent>
{categoriesLoading ? (
<div className="space-y-2">
{Array.from({ length: 8 }).map((_, i) => (
<Skeleton key={`cat-skel-${i}`} className="h-8 w-full" />
))}
</div>
) : viewMode === "grid" ? (
<CategoryGrid
categories={categoryTree || []}
vehicleId={modelId}
catalogMode
brandName={brandName}
variantSearch={variantSearch}
/>
) : (
<CategoryTree
categories={categoryTree || []}
vehicleId={modelId}
catalogMode
brandName={brandName}
variantSearch={variantSearch}
/>
)}
</CardContent>
</Card>
)}
</div>
);
}

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
> **Automotive parts search platform** for the Turkish market with VIN decoding, subscription-based access, and multi-source parts catalog integration. > **Automotive parts search platform** for the Turkish market with VIN decoding, subscription-based access, and multi-source parts catalog integration.
> **URL:** https://sase.tr | **Repo:** `/home/s/ss` > **URL:** https://sase.tr | **Repo:** `/home/s/ss`
Generated: 2026-02-17 Generated: 2026-03-02
--- ---
@@ -108,12 +108,13 @@ sase.tr/
│ │ │ ├── vehicles/ # VIN decoding + vehicle history │ │ │ ├── vehicles/ # VIN decoding + vehicle history
│ │ │ ├── categories/ # Parts category tree │ │ │ ├── categories/ # Parts category tree
│ │ │ ├── parts/ # Auto parts catalog │ │ │ ├── parts/ # Auto parts catalog
│ │ │ ├── catalog/ # VIN-less catalog browser (PL24 model families)
│ │ │ ├── translations/ # Automotive term translations │ │ │ ├── translations/ # Automotive term translations
│ │ │ ├── admin/ # Admin dashboard endpoints │ │ │ ├── admin/ # Admin dashboard endpoints
│ │ │ ├── analytics/ # Usage analytics tracking │ │ │ ├── analytics/ # Usage analytics tracking
│ │ │ ├── common/ # Shared guards, pipes, interceptors, filters, decorators │ │ │ ├── common/ # Shared guards, pipes, interceptors, filters, decorators
│ │ │ ├── config/ # Runtime configuration │ │ │ ├── config/ # Runtime configuration
│ │ │ ├── database/ # Drizzle ORM setup + schemas │ │ │ ├── database/ # Drizzle ORM setup + schemas (core, emex, pl24, parts-catalogs, relations)
│ │ │ ├── redis/ # Redis client module │ │ │ ├── redis/ # Redis client module
│ │ │ ├── storage/ # MinIO/S3 service │ │ │ ├── storage/ # MinIO/S3 service
│ │ │ ├── email/ # Postal email service │ │ │ ├── email/ # Postal email service
@@ -122,6 +123,7 @@ sase.tr/
│ │ │ └── integrations/ # External API integrations │ │ │ └── integrations/ # External API integrations
│ │ │ ├── corgi/ # Offline VIN WMI decoder │ │ │ ├── corgi/ # Offline VIN WMI decoder
│ │ │ ├── pl24/ # PL24 parts catalog API + parsers │ │ │ ├── pl24/ # PL24 parts catalog API + parsers
│ │ │ ├── parts-catalogs/ # PartsCatalogs API (groups, parts, auth)
│ │ │ ├── emex/ # EMEX scraper (Playwright) │ │ │ ├── emex/ # EMEX scraper (Playwright)
│ │ │ └── vin-api/ # NHTSA VIN API fallback │ │ │ └── vin-api/ # NHTSA VIN API fallback
│ │ ├── drizzle.config.ts │ │ ├── drizzle.config.ts
@@ -136,7 +138,7 @@ sase.tr/
│ │ ├── index.tsx # Landing page │ │ ├── index.tsx # Landing page
│ │ ├── _auth.tsx # Auth layout (login, register, etc.) │ │ ├── _auth.tsx # Auth layout (login, register, etc.)
│ │ ├── dashboard.tsx # Dashboard layout (protected) │ │ ├── dashboard.tsx # Dashboard layout (protected)
│ │ └── dashboard/ # Dashboard subroutes │ │ └── dashboard/ # Dashboard subroutes (catalog, vehicles, admin, etc.)
│ ├── components/ # React components │ ├── components/ # React components
│ │ ├── admin/ # DailyChart │ │ ├── admin/ # DailyChart
│ │ ├── schema/ # SchemaViewer, HotspotOverlay, PartsPanel, SchemaToolbar │ │ ├── schema/ # SchemaViewer, HotspotOverlay, PartsPanel, SchemaToolbar
@@ -195,6 +197,7 @@ sase.tr/
| **VehiclesModule** | module, service, controller, spec | VIN decode (multi-source fallback), vehicle history, brand access check | | **VehiclesModule** | module, service, controller, spec | VIN decode (multi-source fallback), vehicle history, brand access check |
| **CategoriesModule** | module, service, controller, spec | Hierarchical category tree, schema pictures | | **CategoriesModule** | module, service, controller, spec | Hierarchical category tree, schema pictures |
| **PartsModule** | module, service, controller, spec | Parts by category, OEM code search | | **PartsModule** | module, service, controller, spec | Parts by category, OEM code search |
| **CatalogModule** | module, service, controller, dto | VIN-less PL24 catalog browser: brands, models, category trees, parts |
| **TranslationsModule** | module, service, controller, spec | Automotive term translation (Redis → DB → Dictionary fallback) | | **TranslationsModule** | module, service, controller, spec | Automotive term translation (Redis → DB → Dictionary fallback) |
| **AdminModule** | module, service, controller, spec | Dashboard stats, user management, payment approval, analytics | | **AdminModule** | module, service, controller, spec | Dashboard stats, user management, payment approval, analytics |
| **AnalyticsModule** | module, service, controller | Usage analytics tracking | | **AnalyticsModule** | module, service, controller | Usage analytics tracking |
@@ -230,12 +233,15 @@ sase.tr/
### Integrations ### Integrations
**VIN Decode Fallback Chain:** Corgi (offline WMI) → PL24 API → EMEX Scraper → NHTSA VIN API **VIN Decode Fallback Chain:** Corgi (offline WMI) → **PartsCatalogs API** PL24 API → EMEX Scraper → NHTSA VIN API
**Category Fetch Fallback Chain (per source):** DB cache → PL24 → PartsCatalogs → EMEX (triggered by `getCategoryTree`)
| Integration | Type | Path | Notes | | Integration | Type | Path | Notes |
|-------------|------|------|-------| |-------------|------|------|-------|
| **Corgi** | Offline DB | `corgi/` | WMI database for brand identification (+ spec) | | **Corgi** | Offline DB | `corgi/` | WMI database for brand identification (+ spec) |
| **PL24** | REST API | `pl24/` | Multi-brand catalog API + auth + parsers (BMW, Mercedes, Generic, Ford Legacy) | | **PL24** | REST API | `pl24/` | Multi-brand catalog API + auth + parsers (BMW, Mercedes, Generic, Ford Legacy) |
| **PartsCatalogs** | REST API | `parts-catalogs/` | Multi-brand catalog API. Files: service, auth-service, module, types. Supports fetchGroups, fetchParts with parameterized car queries |
| **EMEX** | Browser scraper | `emex/` | Playwright-based (emexdwc.ae), async via BullMQ. Files: service, browser, mapper, types | | **EMEX** | Browser scraper | `emex/` | Playwright-based (emexdwc.ae), async via BullMQ. Files: service, browser, mapper, types |
| **VIN-API** | REST API | `vin-api/` | NHTSA VIN decoder (last-resort fallback) | | **VIN-API** | REST API | `vin-api/` | NHTSA VIN decoder (last-resort fallback) |
| **Iyzico** | Payment API | — | Turkish payment processor for card payments | | **Iyzico** | Payment API | — | Turkish payment processor for card payments |
@@ -249,6 +255,7 @@ sase.tr/
- `core.ts` — Main application tables - `core.ts` — Main application tables
- `emex.ts` — EMEX scraper cache tables - `emex.ts` — EMEX scraper cache tables
- `pl24.ts` — PL24 catalog cache tables - `pl24.ts` — PL24 catalog cache tables
- `parts-catalogs.ts` — PartsCatalogs API cache tables
- `relations.ts` — Drizzle ORM relationships - `relations.ts` — Drizzle ORM relationships
#### Core Tables #### Core Tables
@@ -289,20 +296,28 @@ payments
└── Indexes: userId, status └── Indexes: userId, status
vehicles vehicles
├── id (uuid, PK), userId → users, vin, brandId → brands ├── id (uuid, PK), vin (unique), brandId → brands
├── brandName, model, year, engine, transmission, bodyType, market ├── brandName, model, year, engine, transmission, bodyType, market
├── rawData (jsonb), source ├── rawData (jsonb), source
└── Indexes: userId, vin, unique(userId, vin) └── Indexes: vin
Note: Shared across users; access via userVehicles junction table
userVehicles (junction)
├── userId → users, vehicleId → vehicles
├── lastAccessedAt
└── Unique: (userId, vehicleId)
categories categories
├── id (uuid, PK), vehicleId → vehicles, name, nameOriginal ├── id (uuid, PK), vehicleId → vehicles (nullable), catalogVehicleId → catalogVehicles (nullable)
├── parentId (self-ref), externalId, source ├── name, nameOriginal, parentId (self-ref), externalId, source
└── Indexes: vehicleId, parentId └── Indexes: vehicleId, parentId
Note: DUAL FK — exactly one of vehicleId (VIN-based) or catalogVehicleId (VIN-less) is non-null per row
parts parts
├── id (uuid, PK), vehicleId → vehicles, categoryId → categories ├── id (uuid, PK), vehicleId → vehicles (nullable), catalogVehicleId → catalogVehicles (nullable)
├── oemCode, name, nameOriginal, description, quantity, position, hotspotIndex ├── categoryId → categories, oemCode, name, nameOriginal, description, quantity, position, hotspotIndex
└── Indexes: vehicleId, categoryId, oemCode └── Indexes: vehicleId, categoryId, oemCode
Note: DUAL FK — same pattern as categories
schemaPics schemaPics
├── id (uuid, PK), categoryId → categories ├── id (uuid, PK), categoryId → categories
@@ -324,11 +339,20 @@ passwordResetTokens
emexCategoryTranslations emexCategoryTranslations
└── id, originalName (unique), translatedName, isManual └── id, originalName (unique), translatedName, isManual
catalogVehicles
├── id (uuid, PK), source (pl24), serviceName, brandName, brandId → brands
├── model, year, engine, bodyType, transmission, market
├── serviceVehicleId, catalogPath, architecture (P5_MODERN/P4_LEGACY)
├── metadata (jsonb), categoriesFetched (bool)
└── Unique: (serviceName, serviceVehicleId)
Note: categories and parts tables both have catalogVehicleId FK (nullable) for VIN-less catalog data
``` ```
#### Integration Tables #### Integration Tables
- `pl24_*` — PL24 catalog cache (catalogs, vehicles, VINs, part groups, parts, schemas) - `pl24_*` — PL24 catalog cache (catalogs, vehicles, VINs, part groups, parts, schemas)
- `emex_*` — EMEX scraper cache (similar structure with translations) - `emex_*` — EMEX scraper cache (similar structure with translations)
- `parts_catalogs_*` — PartsCatalogs API cache (defined in `parts-catalogs.ts`)
### Job Queues ### Job Queues
@@ -337,10 +361,11 @@ emexCategoryTranslations
| Queue | Trigger | Schedule | Action | | Queue | Trigger | Schedule | Action |
|-------|---------|----------|--------| |-------|---------|----------|--------|
| `EMEX_SCRAPE` | On-demand (VIN decode) | — | Scrapes EMEX via Playwright, stores results | | `EMEX_SCRAPE` | On-demand (VIN decode) | — | Scrapes EMEX via Playwright, stores results |
| `CATALOG_PREFETCH` | On-demand (after VIN decode) | — | Prefetches category tree + parts for all sources (depth-limited, rate-limited, cooldown-guarded). Handled by `PrefetchWorkerService`. |
| `SUBSCRIPTION_EXPIRY` | Cron | Daily 3:00 AM | Expires ended subscriptions, removes brand access | | `SUBSCRIPTION_EXPIRY` | Cron | Daily 3:00 AM | Expires ended subscriptions, removes brand access |
| `QUERY_CLEANUP` | Cron | Weekly Sun 4:00 AM | Cleans old query log entries | | `QUERY_CLEANUP` | Cron | Weekly Sun 4:00 AM | Cleans old query log entries |
**Files:** `apps/api/src/jobs/``jobs.module.ts`, `bull.config.ts`, `processors/`, `queues/` **Files:** `apps/api/src/jobs/``jobs.module.ts`, `bull.config.ts`, `processors/`, `queues/`, `prefetch-worker.service.ts`, `prefetch-utils.ts`, `prefetch.types.ts`
### Telemetry ### Telemetry
@@ -440,6 +465,21 @@ Instrumentation: Express, HTTP, ioredis, NestJS Core, BullMQ, Drizzle ORM
| `GET` | `/api/parts/search?oem=` | User | Search parts by OEM code | | `GET` | `/api/parts/search?oem=` | User | Search parts by OEM code |
| `GET` | `/api/parts/:id` | User | Part by ID | | `GET` | `/api/parts/:id` | User | Part by ID |
#### Catalog (VIN-less Browser)
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| `GET` | `/api/catalog/brands` | User | List PL24 brands with access flags (hasAccess per subscription) |
| `GET` | `/api/catalog/brands/:brandName/catalogs` | User | Service catalog list for a brand (multi-catalog brands like Ford) |
| `GET` | `/api/catalog/brands/:brandName/models` | User | Model list for a brand (`?service=` optional) — DB cache → PL24 fetch |
| `GET` | `/api/catalog/vehicles/:id` | User | Get a catalog vehicle by ID |
| `GET` | `/api/catalog/vehicles/:id/ford-config` | User | Ford model-year/engine/gearbox options (Legacy Ford brands) |
| `GET` | `/api/catalog/vehicles/:id/psa-bodies` | User | PSA body style options (Citroën/Peugeot) |
| `GET` | `/api/catalog/vehicles/:id/psa-engines` | User | PSA engine options for a given body (`?body=`) |
| `GET` | `/api/catalog/vehicles/:id/psa-gearboxes` | User | PSA gearbox options for a given body+engine (`?body=&engine=`) |
| `GET` | `/api/catalog/vehicles/:id/categories` | User | Category tree (`?body=&engine=&gearbox=`); Redis cached 2h |
| `GET` | `/api/catalog/vehicles/:id/categories/:categoryId` | User | Sub-categories or parts+schema (`?body=&engine=&gearbox=`); lazy PL24 fetch |
| `POST` | `/api/catalog/explore/:serviceName` | Admin | Explore PL24 service structure (discovery tool) |
#### Translations #### Translations
| Method | Path | Auth | Description | | Method | Path | Auth | Description |
|--------|------|------|-------------| |--------|------|------|-------------|
@@ -459,6 +499,11 @@ Instrumentation: Express, HTTP, ioredis, NestJS Core, BullMQ, Drizzle ORM
| `GET` | `/api/admin/referrals` | Admin | Referral stats (paginated) | | `GET` | `/api/admin/referrals` | Admin | Referral stats (paginated) |
| `GET` | `/api/admin/stats/daily` | Admin | Daily VIN decode stats (last 30 days) | | `GET` | `/api/admin/stats/daily` | Admin | Daily VIN decode stats (last 30 days) |
#### Analytics
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| `POST` | `/api/analytics/oem-copy` | User | Track OEM code copy event (oemCode, partId?, vehicleId?, categoryId?) |
### Authentication ### Authentication
**Provider:** Better Auth 1.2 **Provider:** Better Auth 1.2
@@ -481,7 +526,7 @@ Flow:
### Routes & Pages ### Routes & Pages
**Router:** TanStack Router (file-based, auto-generated route tree — 31 files) **Router:** TanStack Router (file-based, auto-generated route tree — 36 files)
#### Public #### Public
| Path | Route File | Description | | Path | Route File | Description |
@@ -490,7 +535,8 @@ Flow:
| `/pricing` | `routes/pricing.tsx` | Plan comparison (1/2/3 brand, full package) | | `/pricing` | `routes/pricing.tsx` | Plan comparison (1/2/3 brand, full package) |
| `/about` | `routes/about.tsx` | About page | | `/about` | `routes/about.tsx` | About page |
| `/contact` | `routes/contact.tsx` | Contact page | | `/contact` | `routes/contact.tsx` | Contact page |
| `/blog` | `routes/blog.tsx` | Blog page | | `/blog` | `routes/blog.tsx` | Blog listing page |
| `/blog/:slug` | `routes/blog_/$slug.tsx` | Blog post detail (SEO pre-rendered) |
| `/demo` | `routes/demo.tsx` | Demo page | | `/demo` | `routes/demo.tsx` | Demo page |
| `/privacy` | `routes/privacy.tsx` | Privacy policy | | `/privacy` | `routes/privacy.tsx` | Privacy policy |
| `/terms` | `routes/terms.tsx` | Terms of service | | `/terms` | `routes/terms.tsx` | Terms of service |
@@ -517,6 +563,14 @@ Flow:
| `/dashboard/vehicles/$id` | `routes/dashboard/vehicles_/$id/index.tsx` | Vehicle details | | `/dashboard/vehicles/$id` | `routes/dashboard/vehicles_/$id/index.tsx` | Vehicle details |
| `/dashboard/vehicles/$id/categories/$categoryId` | `routes/dashboard/vehicles_/$id/categories_/$categoryId.tsx` | Interactive schema + parts table | | `/dashboard/vehicles/$id/categories/$categoryId` | `routes/dashboard/vehicles_/$id/categories_/$categoryId.tsx` | Interactive schema + parts table |
#### Catalog Browser (VIN-less, Protected)
| Path | Route File | Description |
|------|------------|-------------|
| `/dashboard/catalog` | `routes/dashboard/catalog/index.tsx` | Brand grid with hasAccess flags; locked brands show upgrade CTA |
| `/dashboard/catalog/$brandName` | `routes/dashboard/catalog_/$brandName/index.tsx` | Model list for brand (fetched from PL24) |
| `/dashboard/catalog/$brandName/$modelId` | `routes/dashboard/catalog_/$brandName_/$modelId/index.tsx` | Vehicle details + category tree (grid/tree toggle) |
| `/dashboard/catalog/$brandName/$modelId/categories/$categoryId` | `routes/dashboard/catalog_/$brandName_/$modelId/categories_/$categoryId.tsx` | Category sub-groups or schema+parts (lazy PL24 fetch) |
#### Admin (Role-based) #### Admin (Role-based)
| Path | Route File | Description | | Path | Route File | Description |
|------|------------|-------------| |------|------------|-------------|
@@ -537,12 +591,15 @@ Flow:
| **SchemaToolbar** | `components/schema/schema-toolbar.tsx` | Zoom/reset/fullscreen controls | | **SchemaToolbar** | `components/schema/schema-toolbar.tsx` | Zoom/reset/fullscreen controls |
| **BrandSelector** | `components/subscription/brand-selector.tsx` | Brand grid with plan-enforced max selection | | **BrandSelector** | `components/subscription/brand-selector.tsx` | Brand grid with plan-enforced max selection |
| **VehicleCard** | `components/vehicles/vehicle-card.tsx` | Vehicle info card (VIN, brand, model, year) | | **VehicleCard** | `components/vehicles/vehicle-card.tsx` | Vehicle info card (VIN, brand, model, year) |
| **VehicleSelectModal** | `components/vehicles/vehicle-select-modal.tsx` | Modal for selecting a vehicle from history (used during VIN decode flow) |
| **VinInput** | `components/vehicles/vin-input.tsx` | VIN entry input component | | **VinInput** | `components/vehicles/vin-input.tsx` | VIN entry input component |
| **CategoryTree** | `components/categories/category-tree.tsx` | Recursive expandable category hierarchy | | **CategoryTree** | `components/categories/category-tree.tsx` | Recursive expandable category hierarchy |
| **CategoryGrid** | `components/categories/category-grid.tsx` | Grid layout for category browsing | | **CategoryGrid** | `components/categories/category-grid.tsx` | Grid layout for category browsing |
| **DailyChart** | `components/admin/daily-chart.tsx` | Daily VIN decode stats chart | | **DailyChart** | `components/admin/daily-chart.tsx` | Daily VIN decode stats chart |
| **PaymentContent** | `components/payment/payment-content.tsx` | Payment form and flow | | **PaymentContent** | `components/payment/payment-content.tsx` | Payment form and flow |
| **SettingsContent** | `components/settings/settings-content.tsx` | User settings panel content | | **SettingsContent** | `components/settings/settings-content.tsx` | User settings panel content |
| **PsaVariantSelector** | `components/catalog/psa-variant-selector.tsx` | PSA (Citroën/Peugeot) body/engine/gearbox picker for VIN-less catalog |
| **FordVariantSelector** | `components/catalog/ford-variant-selector.tsx` | Ford model-year/engine/gearbox picker for VIN-less catalog |
**UI primitives** from `@sase/ui`: Button, Card, Input, Label, Badge, Dialog, Tabs, Separator, Skeleton **UI primitives** from `@sase/ui`: Button, Card, Input, Label, Badge, Dialog, Tabs, Separator, Skeleton
@@ -554,6 +611,7 @@ Flow:
| `useAuth()` | Auth state + Better Auth client (`user`, `isAdmin`, `signIn`, `signUp`, `signOut`, `session`) | | `useAuth()` | Auth state + Better Auth client (`user`, `isAdmin`, `signIn`, `signUp`, `signOut`, `session`) |
| `useCategoryParts(vehicleId, categoryId)` | TanStack Query for schema + parts + hotspots | | `useCategoryParts(vehicleId, categoryId)` | TanStack Query for schema + parts + hotspots |
| `useSchemaInteraction()` | Pan/zoom/pinch event handlers for schema viewer | | `useSchemaInteraction()` | Pan/zoom/pinch event handlers for schema viewer |
| `usePageMeta(options)` | Sets `<title>`, meta description, canonical, OG/Twitter tags; restores defaults on unmount |
**Stores (Zustand):** **Stores (Zustand):**
| Store | State | | Store | State |
@@ -643,6 +701,7 @@ Dependencies: Radix UI (dialog, dropdown-menu, label, popover, select, separator
### Playwright 1.50 ### Playwright 1.50
- Installed at root level (`package.json`) - Installed at root level (`package.json`)
- Used by EMEX integration (`emex.browser.ts`) for web scraping - Used by EMEX integration (`emex.browser.ts`) for web scraping
- Used by PartsCatalogs auth service for JWT capture via Playwright
- Test scripts in `scripts/` (vin-e2e-test.js) - Test scripts in `scripts/` (vin-e2e-test.js)
--- ---
@@ -657,6 +716,13 @@ Dependencies: Radix UI (dialog, dropdown-menu, label, popover, select, separator
| Redis 7.4 | `redis:7.4-alpine` | 127.0.0.1:6379 | `redis_data` | | Redis 7.4 | `redis:7.4-alpine` | 127.0.0.1:6379 | `redis_data` |
| MinIO | `minio/minio` | 9000 (API), 9001 (Console) | `minio_data` | | MinIO | `minio/minio` | 9000 (API), 9001 (Console) | `minio_data` |
### SEO Infrastructure
- `apps/web/scripts/prerender.mjs` — Pre-renders public pages to static HTML (landing, blog posts, pricing, etc.) for crawler/bot visibility
- `apps/web/public/robots.txt` — Crawl directives with sitemap reference
- `apps/web/public/sitemap.xml` — Static sitemap for public pages
- `apps/web/index.html` — Contains default OG/Twitter meta tags; `usePageMeta()` overrides at runtime per page
### Nginx (`docker/nginx/sites/`) ### Nginx (`docker/nginx/sites/`)
- `sase.tr.conf` — Frontend SPA + `/api` proxy + `/collect/` Faro telemetry CORS proxy + gzip (level 6) + 1-year asset cache + security headers - `sase.tr.conf` — Frontend SPA + `/api` proxy + `/collect/` Faro telemetry CORS proxy + gzip (level 6) + 1-year asset cache + security headers

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

View File

@@ -0,0 +1,58 @@
# PL24 Katalog Keşif Özeti
## Keşif Tarihi
2026-02-24T13:32:39.082Z
## Sonuçlar
| Marka | Slug | Durum | API İstek Sayısı |
|-------|------|-------|-----------------|
| Alpine | alpine | tamamlandı | 18 |
| Audi | audi | tamamlandı | 17 |
| Bentley | bentley | tamamlandı | 7 |
| BMW | bmw | tamamlandı | 11 |
| BMW Classic | bmw-classic | tamamlandı | 10 |
| BMW Motorrad | bmw-motorrad | tamamlandı | 10 |
| BMW Motorrad Classic | bmw-motorrad-classic | tamamlandı | 10 |
| Citroën | citro-n | tamamlandı | 0 |
| Citroën DS | citro-n-ds | tamamlandı | 0 |
| Cupra | cupra | tamamlandı | 7 |
| Dacia | dacia | tamamlandı | 9 |
| Ford | ford | tamamlandı | 13 |
| Ford Commercial | ford-commercial | tamamlandı | 12 |
| Hyundai | hyundai | tamamlandı | 0 |
| Infiniti | infiniti | tamamlandı | 0 |
| Jaguar | jaguar | tamamlandı | 7 |
| Kia | kia | tamamlandı | 0 |
| Land Rover | land-rover | tamamlandı | 7 |
| Lexus | lexus | tamamlandı | 11 |
| MAN | man | tamamlandı | 6 |
| Mercedes-Benz | mercedes-benz | tamamlandı | 6 |
| Mercedes-Benz Classic | mercedes-benz-classic | tamamlandı | 7 |
| Mercedes-Benz Trucks | mercedes-benz-trucks | tamamlandı | 9 |
| Mercedes-Benz Unimog | mercedes-benz-unimog | tamamlandı | 6 |
| Mercedes-Benz Vans | mercedes-benz-vans | tamamlandı | 8 |
| MINI | mini | tamamlandı | 10 |
| MINI Classic | mini-classic | tamamlandı | 10 |
| Mitsubishi | mitsubishi | tamamlandı | 9 |
| Nissan | nissan | tamamlandı | 0 |
| Opel | opel | tamamlandı | 0 |
| Peugeot | peugeot | tamamlandı | 0 |
| Polestar | polestar | tamamlandı | 0 |
| Porsche | porsche | tamamlandı | 7 |
| Porsche Classic | porsche-classic | tamamlandı | 7 |
| Renault | renault | tamamlandı | 9 |
| SEAT | seat | tamamlandı | 7 |
| Škoda | koda | tamamlandı | 7 |
| smart | smart | tamamlandı | 8 |
| Suzuki | suzuki | tamamlandı | 8 |
| Toyota | toyota | tamamlandı | 11 |
| Vauxhall | vauxhall | tamamlandı | 0 |
| Volkswagen | volkswagen | tamamlandı | 7 |
| Volkswagen Classic | volkswagen-classic | tamamlandı | 7 |
| Volkswagen Commercial Vehicles | volkswagen-commercial-vehicles | tamamlandı | 7 |
| Volvo | volvo | tamamlandı | 0 |
## Notlar
- Bu dosya otomatik olarak oluşturulmuştur
- Her marka için ayrıntı: `{slug}.md`

156
docs/pl24-catalog/alpine.md Normal file
View File

@@ -0,0 +1,156 @@
# Alpine — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:20:40.295Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /auth/ext/api/1.1/authorize
- **Method:** POST
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/auth/ext/api/1.1/authorize`
- **Yanıt özeti:**
`{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXphdGlvbiIsImFsZyI6IlJTMjU2In0.eyJpYXQiOjE3NzE5MzkyNDAsImV4cCI6MTc3MTkzOTg0MCwic2lkIjoiN2h4RHEyYmtVaWtHc3F1LURLeldxb25DX25xTHE5SXkiLCJhaWQiOjE0OTg1ODMsInVpZCI6MjE0NDA5NCwic2VydmljZXMiOlsicGwyNC10bHMtcGl`
- **Çağrı sayısı:** 3
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/TR/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/TR/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-manufacturer/ext/api/1.0/manufacturers/
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-manufacturer/ext/api/1.0/manufacturers/?lang=tr&country=TR&relativeLink=true`
- **Yanıt özeti:**
`{"manufacturers":[{"imgSrc":"/carbrands/alpine/pl24_cat_logo_app.png","label":"Alpine","link":"/pl24-app/alpine_parts/0/0?lang=tr","serviceName":"alpine_parts","translation":"Alpine","architecture":"P5","catmetaUrl":"/p5renault/extern/catmeta?serviceName=alpine_parts&country=TR&lang=tr"},{"imgSrc":"`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /cart/ext/api/3.0
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/cart/ext/api/3.0?jwt=eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjo...`
- **Yanıt özeti:**
`{"_links":{"carts":{"href":"/cart/ext/api/2.0/carts?catalogService={catalogService}","templated":true},"templates":{"href":"/cart/ext/api/2.0/templates?catalog={catalog}","templated":true}}}`
- **Çağrı sayısı:** 2
### /p5renault/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/catmeta?serviceName=alpine_parts&country=TR&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Alpine", "user24Brand" : "Alpine", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAABtQTFRFR3BMAGu9AGq7AG26AG27AG66AG+6AG+6AG+6DNix8gAAAAh0Uk5TABA/b57E5PR1jDNtAAAFMUlEQVR42u2cTW/jNhRF9eFm7WKUzFYFaidLrcZe2qtq`
- **Çağrı sayısı:** 1
### /lex-campaign/ext/api/1.0/DestinationContent
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/lex-campaign/ext/api/1.0/DestinationContent?destinationId=catalog_alpine_parts&countryCode=T...`
- **Yanıt özeti:**
`{"components":[]}`
- **Çağrı sayısı:** 1
### /pl24-dealers/ext/api/2.0/catalogDealers
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-dealers/ext/api/2.0/catalogDealers?catalogService=alpine_parts`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /cart/ext/api/2.0/contextCart
- **Method:** GET
- **Status:** 410
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=alpine_parts&uname=header&_=1771939241`
- **Yanıt özeti:**
`{"type":"urn:pl24-ShoppingCart-v2:notFound","title":"Erişim hatası","detail":"Sepete erişim hatası: contextCart for catalog service: 'alpine_parts' is not available.","references":{},"context":{}}`
- **Çağrı sayısı:** 2
### /p5renault/extern/vehicle/catalogs
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=alpine_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Alpine", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=alpine_parts&upds=2025-12-02--14-31" } } ], "demo" : false, "data" : { "records" : [ { "id" : "XEF", "description" :`
- **Çağrı sayısı:** 2
### /pl24-ordrimprt/ext/api/1.0/order
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-ordrimprt/ext/api/1.0/order?catalogService=alpine_parts&lang=tr`
- **Yanıt özeti:**
`{}`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| POST | `https://www.partslink24.com/auth/ext/api/1.1/authorize` | 200 | marka-ana-sayfa | `{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXp` |
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| POST | `https://www.partslink24.com/auth/ext/api/1.1/authorize` | 200 | marka-ana-sayfa | `{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXp` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-manufacturer/ext/api/1.0/manufacturers/?lang=tr...` | 200 | marka-ana-sayfa | `{"manufacturers":[{"imgSrc":"/carbrands/alpine/pl24_cat_logo_app.png","label":"Alpine","link":"/pl24` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/cart/ext/api/3.0?jwt=eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImt...` | 200 | marka-ana-sayfa | `{"_links":{"carts":{"href":"/cart/ext/api/2.0/carts?catalogService={catalogService}","templated":tru` |
| GET | `https://www.partslink24.com/p5renault/extern/catmeta?serviceName=alpine_parts&co...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Alpine", "user24Brand" : "Alpine", ` |
| POST | `https://www.partslink24.com/auth/ext/api/1.1/authorize` | 200 | marka-ana-sayfa | `{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXp` |
| GET | `https://www.partslink24.com/pl24-manufacturer/ext/api/1.0/manufacturers/?lang=tr...` | 200 | marka-ana-sayfa | `{"manufacturers":[{"imgSrc":"/carbrands/alpine/pl24_cat_logo_app.png","label":"Alpine","link":"/pl24` |
| GET | `https://www.partslink24.com/cart/ext/api/3.0?jwt=eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImt...` | 200 | marka-ana-sayfa | `{"_links":{"carts":{"href":"/cart/ext/api/2.0/carts?catalogService={catalogService}","templated":tru` |
| GET | `https://www.partslink24.com/lex-campaign/ext/api/1.0/DestinationContent?destinat...` | 200 | marka-ana-sayfa | `{"components":[]}` |
| GET | `https://www.partslink24.com/pl24-dealers/ext/api/2.0/catalogDealers?catalogServi...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=alpine_p...` | 410 | marka-ana-sayfa | `{"type":"urn:pl24-ShoppingCart-v2:notFound","title":"Erişim hatası","detail":"Sepete erişim hatası: ` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Alpine", "link" : { "wid" : "catalogTable", "path" ` |
| GET | `https://www.partslink24.com/pl24-ordrimprt/ext/api/1.0/order?catalogService=alpi...` | 200 | marka-ana-sayfa | `{}` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=alpine_p...` | 410 | marka-ana-sayfa | `{"type":"urn:pl24-ShoppingCart-v2:notFound","title":"Erişim hatası","detail":"Sepete erişim hatası: ` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Alpine", "link" : { "wid" : "catalogTable", "path" ` |
## Notlar
- Sayfa başlığı: partslink24
- URL: https://www.partslink24.com/pl24-app/alpine_parts/0/0?desktop=true&lang=tr
- İlk model tıklanamadı — selector bulunamadı

135
docs/pl24-catalog/audi.md Normal file
View File

@@ -0,0 +1,135 @@
# Audi — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:20:55.755Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/TR/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/TR/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=audi_parts&country=TR&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Audi", "user24Brand" : "Audi", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAACXBIWXMAAAsSAAALEgHS3X78AAAZdklEQVR4nO3dXVLcyJrG8fSE7jEx4Ws4C/DABPY19AqaswLwCppegfEKulhBFytoWEHDtSEONV7Aoa4dE3bdVwQnZL+yZblUpVfKr7fq/4sg6Db1lZXK`
- **Çağrı sayısı:** 1
### /auth/ext/api/1.1/authorize
- **Method:** POST
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/auth/ext/api/1.1/authorize`
- **Yanıt özeti:**
`{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXphdGlvbiIsImFsZyI6IlJTMjU2In0.eyJpYXQiOjE3NzE5MzkyNTYsImV4cCI6MTc3MTkzOTg1Niwic2lkIjoiN2h4RHEyYmtVaWtHc3F1LURLeldxb25DX25xTHE5SXkiLCJhaWQiOjE0OTg1ODMsInVpZCI6MjE0NDA5NCwic2VydmljZXMiOlsicGwyNC10bHMtcGl`
- **Çağrı sayısı:** 1
### /lex-campaign/ext/api/1.0/DestinationContent
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/lex-campaign/ext/api/1.0/DestinationContent?destinationId=catalog_audi_parts&countryCode=TR&...`
- **Yanıt özeti:**
`{"components":[]}`
- **Çağrı sayısı:** 1
### /pl24-dealers/ext/api/2.0/catalogDealers
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-dealers/ext/api/2.0/catalogDealers?catalogService=audi_parts`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /cart/ext/api/2.0/contextCart
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_parts&uname=header&_=1771939256`
- **Yanıt özeti:**
`{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-13T18:00:56.636Z","cartName":"Audi #2","customerReference":"Audi #2","catalogProperties":{"catalogService":"audi_parts","brandName":"Audi","brandNamePretty":"Audi","brandLogoPath":"/carbrands/audi/pl24`
- **Çağrı sayısı:** 7
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=audi_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Audi", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=audi_parts&upds=2026-02-13--00-01" } } ], "demo" : false, "data" : { "records" : [ { "id" : "91`
- **Çağrı sayısı:** 2
### /pl24-ordrimprt/ext/api/1.0/order
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-ordrimprt/ext/api/1.0/order?catalogService=audi_parts&lang=tr`
- **Yanıt özeti:**
`{}`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=audi_parts&country...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Audi", "user24Brand" : "Audi", "l` |
| POST | `https://www.partslink24.com/auth/ext/api/1.1/authorize` | 200 | marka-ana-sayfa | `{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXp` |
| GET | `https://www.partslink24.com/lex-campaign/ext/api/1.0/DestinationContent?destinat...` | 200 | marka-ana-sayfa | `{"components":[]}` |
| GET | `https://www.partslink24.com/pl24-dealers/ext/api/2.0/catalogDealers?catalogServi...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Audi", "link" : { "wid" : "modelFamiliesTable", "pa` |
| GET | `https://www.partslink24.com/pl24-ordrimprt/ext/api/1.0/order?catalogService=audi...` | 200 | marka-ana-sayfa | `{}` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Audi", "link" : { "wid" : "modelFamiliesTable", "pa` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
| GET | `https://www.partslink24.com/cart/ext/api/2.0/contextCart?catalogService=audi_par...` | 200 | marka-ana-sayfa | `{"cartId":13076569,"cartHref":null,"creationTime":"2025-03-13T18:00:56.636Z","updateTime":"2025-03-1` |
## Notlar
- Sayfa başlığı: partslink24
- URL: https://www.partslink24.com/pl24-app/audi_parts/0/0?desktop=true&lang=tr
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,95 @@
# Bentley — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:21:11.127Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=bentley_parts&country=TR&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Bentley", "user24Brand" : "Bentley", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9lZWXo6Og1NTWUlJS9vb1JW7H1AAAADnRSTlMAzX`
- **Çağrı sayısı:** 1
### /auth/ext/api/1.1/authorize
- **Method:** POST
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/auth/ext/api/1.1/authorize`
- **Yanıt özeti:**
`{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXphdGlvbiIsImFsZyI6IlJTMjU2In0.eyJpYXQiOjE3NzE5MzkyNzEsImV4cCI6MTc3MTkzOTg3MSwic2lkIjoiN2h4RHEyYmtVaWtHc3F1LURLeldxb25DX25xTHE5SXkiLCJzZXJ2aWNlcyI6W10sImFwcCI6InBhcnRzbGluazI0IiwidHlwZSI6InBsMjQtYXV0aG9`
- **Çağrı sayısı:** 1
### /pl24-appgtw/ext/api/1.0/logout
- **Method:** POST
- **Status:** 204
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/logout`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /carbrands/ford/pl24_portal_logo_v2.png
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/carbrands/ford/pl24_portal_logo_v2.png`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=bentley_parts&coun...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Bentley", "user24Brand" : "Bentley", ` |
| POST | `https://www.partslink24.com/auth/ext/api/1.1/authorize` | 200 | marka-ana-sayfa | `{"access_token":"eyJhcHAiOiJwYXJ0c2xpbmsyNCIsImtpZCI6InByLXBsMjRqd2tzLWtpZDEiLCJ0eXBlIjoiYXV0aG9yaXp` |
| POST | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/logout` | 204 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/carbrands/ford/pl24_portal_logo_v2.png` | 200 | marka-ana-sayfa | `` |
## Notlar
- Sayfa başlığı: partslink24
- URL: https://www.partslink24.com/partslink24/user/login.do
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,118 @@
# BMW Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:22:11.868Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwclassic_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "BMW Classic", "user24Brand" : "BMW", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAACpQTFRFR3BMqbC4lpeYhIWGf4GEfYKHe31/fH1+e3t7eXl5dXV1PXe4b29vAGeylL5pygAAAAx0Uk5TABk0T2mBmbHJ3/PzKqfy3AAACtNJREFUeNrs2NuOsm`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "8'", "link" : { `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=Z4&serviceName=bmwclassic_parts&upds=2026-02-10-...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts&upds=2026-02-10--14-21", "id" : "Z4" } }, { "name" : "Z4", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=Z4&modelType=E85&serviceName=bmwclassic_parts...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts&upds=2026-02-10--14-21", "id" : "Z4" } }, { "name" : "Z4", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=Z4&modelType=E85&res1=Roa&serviceName=bmwclas...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts&upds=2026-02-10--14-21", "id" : "Z4" } }, { "name" : "Z4", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=Z4&modelType=E85&res1=Roa&res2=Z4+2.0i&servic...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwclassic_parts&upds=2026-02-10--14-21", "id" : "Z4" } }, { "name" : "Z4", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwclassic_parts&co...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "BMW Classic", "user24Brand" : "BMW", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwc...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwc...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=Z4&servi...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=Z4&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=Z4&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=Z4&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Classic", "link" : { "wid" : "modelTable", "pat` |
## Notlar
- Sayfa başlığı: BMW Classic, Z4, E85 - partslink24
- URL: https://www.partslink24.com/pl24-app/bmwclassic_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9WjQmbW9kZWxUeXBlPUU4NSZyZXMxPVJvYSZyZXMyPVo0KzIuMGkmc2VydmljZU5hbWU9Ym13Y2xhc3NpY19wYXJ0cyZ1cGRzPTIwMjYtMDItMTAtLTE0LTIxIiwid2lkIjoicmVzdHJpY3Rpb25UYWJsZTMiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,118 @@
# BMW Motorrad Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:22:42.650Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwmotorradclassic_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "BMW Motorrad Classic", "user24Brand" : "BMWMotorrad", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAAIdQTFRFR3BMPDw8NTU2VlZXHh4eX19fcXFxl5iZcnJzYWJjFhYWAQEBExMTJSUlQUFBPT09Tk5OZnaIRUVFSUlJLCwsBAQEMDAwMTExK`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "1-Zyl.", `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=R-Modelle+2V&serviceName=bmwmotorradclassic_part...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts&upds=2026-02-10--14-21", "id" : "R-Modelle 2V" } }, { "name" : "R-Modeller 2V", "link" : { `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=R-Modelle+2V&modelType=2474&serviceName=bmwmo...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts&upds=2026-02-10--14-21", "id" : "R-Modelle 2V" } }, { "name" : "R-Modeller 2V", "link" : { `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=R-Modelle+2V&modelType=2474&res1=ohne&service...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts&upds=2026-02-10--14-21", "id" : "R-Modelle 2V" } }, { "name" : "R-Modeller 2V", "link" : { `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=R-Modelle+2V&modelType=2474&res1=ohne&res2=R+...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorradclassic_parts&upds=2026-02-10--14-21", "id" : "R-Modelle 2V" } }, { "name" : "R-Modeller 2V", "link" : { `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwmotorradclassic_...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "BMW Motorrad Classic", "user24Brand" : ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwm...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwm...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=R-Modell...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=R-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=R-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=R-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad Classic", "link" : { "wid" : "modelTable", ` |
## Notlar
- Sayfa başlığı: BMW Motorrad Classic, R-Modeller 2V, 2474 - partslink24
- URL: https://www.partslink24.com/pl24-app/bmwmotorradclassic_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9Ui1Nb2RlbGxlKzJWJm1vZGVsVHlwZT0yNDc0JnJlczE9b2huZSZyZXMyPVIrMTAwKyUyRjcmc2VydmljZU5hbWU9Ym13bW90b3JyYWRjbGFzc2ljX3BhcnRzJnVwZHM9MjAyNi0wMi0xMC0tMTQtMjEiLCJ3aWQiOiJyZXN0cmljdGlvblRhYmxlMyIsImF1dG8iOnRydWV9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,118 @@
# BMW Motorrad — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:22:27.217Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwmotorrad_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "BMW Motorrad", "user24Brand" : "BMWMotorrad", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAADZQTFRFR3BMAB43AAIDAAcNAAAAAAAAAGexAAAAAAABAAAAAGWwAAAAAAAAAGaxAAAAAAAAAGaxAAAACaFyRgAAABB0Uk5TAAkSHzBCSlxzjJilw`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "C-Modelle", "link" `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=G-Modelle&serviceName=bmwmotorrad_parts&upds=202...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts&upds=2026-02-10--14-21", "id" : "G-Modelle" } }, { "name" : "G-Modeller", "link" : { "wid" : "modelT`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=G-Modelle&modelType=R134&serviceName=bmwmotor...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts&upds=2026-02-10--14-21", "id" : "G-Modelle" } }, { "name" : "G-Modeller", "link" : { "wid" : "modelT`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=G-Modelle&modelType=R134&res1=ohne&serviceNam...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts&upds=2026-02-10--14-21", "id" : "G-Modelle" } }, { "name" : "G-Modeller", "link" : { "wid" : "modelT`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=G-Modelle&modelType=R134&res1=ohne&res2=G+650...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwmotorrad_parts&upds=2026-02-10--14-21", "id" : "G-Modelle" } }, { "name" : "G-Modeller", "link" : { "wid" : "modelT`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmwmotorrad_parts&c...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "BMW Motorrad", "user24Brand" : "BMWMoto` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwm...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmwm...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=G-Modell...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=G-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=G-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=G-Mod...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW Motorrad", "link" : { "wid" : "modelTable", "pa` |
## Notlar
- Sayfa başlığı: BMW Motorrad, G-Modeller, R13 (G 650 GS Sertão) - partslink24
- URL: https://www.partslink24.com/pl24-app/bmwmotorrad_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9Ry1Nb2RlbGxlJm1vZGVsVHlwZT1SMTM0JnJlczE9b2huZSZyZXMyPUcrNjUwK0dTK1NlcnQlQzMlQTNvKyUyODAxMzYlMkMrMDE0NiUyOSZzZXJ2aWNlTmFtZT1ibXdtb3RvcnJhZF9wYXJ0cyZ1cGRzPTIwMjYtMDItMTAtLTE0LTIxIiwid2lkIjoicmVzdHJpY3Rpb25UYWJsZTMiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

129
docs/pl24-catalog/bmw.md Normal file
View File

@@ -0,0 +1,129 @@
# BMW — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:21:56.520Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-manufacturer/ext/api/1.0/manufacturers/
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-manufacturer/ext/api/1.0/manufacturers/?lang=tr&country=DE&relativeLink=true`
- **Yanıt özeti:**
`{"manufacturers":[{"imgSrc":"/carbrands/abarth/pl24_cat_logo_app.png","label":"Abarth","link":"/fiatspa/pl24-entry.action?service=abarth_parts&lang=tr&vin=","serviceName":"abarth_parts","translation":"Abarth","architecture":"P4","catmetaUrl":null},{"imgSrc":"/carbrands/alfa/pl24_cat_logo_app.png","l`
- **Çağrı sayısı:** 1
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmw_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "BMW", "user24Brand" : "BMW", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAADNQTFRFR3BMaG91bG91ZnB6cnJyB2avc3FxB2avcnFxcnFxB2av////2+Lrw8PDl5aWcnFxB2avO/gNwwAAAAt0Uk5TABU5WoCLpsHH6+qyqTnsAAAPfUlEQVR42u2d65`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "1'", "link" : { "wid" : "mod`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=X5&serviceName=bmw_parts&upds=2026-02-10--14-21`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts&upds=2026-02-10--14-21", "id" : "X5" } }, { "name" : "X5", "link" : { "wid" : "modelTypeTable", "path" : "/p5bm`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=X5&modelType=E53&serviceName=bmw_parts&upds=2...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts&upds=2026-02-10--14-21", "id" : "X5" } }, { "name" : "X5", "link" : { "wid" : "modelTypeTable", "path" : "/p5bm`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=X5&modelType=E53&res1=SAV&serviceName=bmw_par...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts&upds=2026-02-10--14-21", "id" : "X5" } }, { "name" : "X5", "link" : { "wid" : "modelTypeTable", "path" : "/p5bm`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=X5&modelType=E53&res1=SAV&res2=X5+4.8is&servi...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_parts&upds=2026-02-10--14-21", "id" : "X5" } }, { "name" : "X5", "link" : { "wid" : "modelTypeTable", "path" : "/p5bm`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-manufacturer/ext/api/1.0/manufacturers/?lang=tr...` | 200 | marka-ana-sayfa | `{"manufacturers":[{"imgSrc":"/carbrands/abarth/pl24_cat_logo_app.png","label":"Abarth","link":"/fiat` |
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=bmw_parts&country=D...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "BMW", "user24Brand" : "BMW", "log` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=bmw_...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=X5&servi...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=X5&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=X5&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=X5&mo...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "BMW", "link" : { "wid" : "modelTable", "path" : "/p` |
## Notlar
- Sayfa başlığı: BMW, X5, E53 - partslink24
- URL: https://www.partslink24.com/pl24-app/bmw_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9WDUmbW9kZWxUeXBlPUU1MyZyZXMxPVNBViZyZXMyPVg1KzQuOGlzJnNlcnZpY2VOYW1lPWJtd19wYXJ0cyZ1cGRzPTIwMjYtMDItMTAtLTE0LTIxIiwid2lkIjoicmVzdHJpY3Rpb25UYWJsZTMiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Citroën DS — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:23:13.597Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Citroën DS - partslink24
- URL: https://www.partslink24.com/psa/citroenDs_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2024.02.13+09%3A27%3A21+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Citroën — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:22:58.028Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Citroën BX - BX - partslink24
- URL: https://www.partslink24.com/psa/citroen_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2024.02.13+09%3A27%3A21+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Cupra — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:23:29.312Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=cupra_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Cupra", "user24Brand" : "Seat", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAABtQTFRFR3BMAAAAAAMDAAMDAQICAQEBAQICAQICAQIClsKUpgAAAAh0Uk5TABo9WX6gxOndduqxAAAGOElEQVR42u3c3VbjOgwFYMmyft7/ic86DG1Km1SxXUpS7+8`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=cupra_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Cupra", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=cupra_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ { "id" : "8`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=87370&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Cupra", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=cupra_parts&upds=2026-02-13--00-01", "id" : "87370_41_null" } }, { "name" : "Formentor (CUPRA)", `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=cupra_parts&countr...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Cupra", "user24Brand" : "Seat", "` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Cupra", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Cupra", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=87370&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Cupra", "link" : { "wid" : "modelFamiliesTable", "p` |
## Notlar
- Sayfa başlığı: Cupra - partslink24
- URL: https://www.partslink24.com/pl24-app/cupra_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT04NzM3MCZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9NDEmc2VydmljZU5hbWU9Y3VwcmFfcGFydHMmdXBkcz0yMDI2LTAyLTEzLS0wMC0wMSIsIndpZCI6Im1vZGVsWWVhclRhYmxlIn0%253D/
- İlk model tıklanamadı — selector bulunamadı

107
docs/pl24-catalog/dacia.md Normal file
View File

@@ -0,0 +1,107 @@
# Dacia — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:23:44.798Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5renault/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/catmeta?serviceName=dacia_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Dacia", "user24Brand" : "Dacia", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAAA9QTFRFR3BMcHBjbHBkbXBlbXBlSUKgdQAAAAR0Uk5TABxOwSQ2rCMAAAImSURBVHja7dhRTupQFEbhg50AUQaA2gFQ6ASAPf8xmRBig+scd48Pxpj1vZlcN3+XTU`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/catalogs
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=dacia_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=dacia_parts&upds=2025-12-02--14-31" } } ], "demo" : true, "data" : { "records" : [ { "id" : "X75", "description" : "D`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/models?catalog=X41&lang=tr&serviceName=dacia_parts&upds=2025-12-02-...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=dacia_parts&upds=2025-12-02--14-31", "id" : "X41" } }, { "name" : "SUPERNOVA / SOLENZA", "link" : { "wid" : "modelTab`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/engines
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/engines?catalog=X41&lang=tr&model=B41&serviceName=dacia_parts&upds=...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=dacia_parts&upds=2025-12-02--14-31", "id" : "X41" } }, { "name" : "SUPERNOVA / SOLENZA", "link" : { "wid" : "modelTab`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/gearbox
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/gearbox?catalog=X41&engineFamily=EXX&engineIndex=262&engineLevel=MA...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=dacia_parts&upds=2025-12-02--14-31", "id" : "X41" } }, { "name" : "SUPERNOVA / SOLENZA", "link" : { "wid" : "modelTab`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5renault/extern/catmeta?serviceName=dacia_parts&cou...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Dacia", "user24Brand" : "Dacia", ` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" :` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" :` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/models?catalog=X41&lang=tr&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" :` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/engines?catalog=X41&lang=tr...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" :` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/gearbox?catalog=X41&engineF...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Dacia", "link" : { "wid" : "catalogTable", "path" :` |
## Notlar
- Sayfa başlığı: Dacia, SUPERNOVA / SOLENZA, 5 KAPILI SEDAN - partslink24
- URL: https://www.partslink24.com/pl24-app/dacia_parts/0/eyJwYXRoIjoiL3A1cmVuYXVsdC9leHRlcm4vdmVoaWNsZS9nZWFyYm94P2NhdGFsb2c9WDQxJmVuZ2luZUZhbWlseT1FWFgmZW5naW5lSW5kZXg9MjYyJmVuZ2luZUxldmVsPU1BJmVuZ2luZVR5cGU9RTdKJmxhbmc9dHImbW9kZWw9QjQxJnNlcnZpY2VOYW1lPWRhY2lhX3BhcnRzJnVwZHM9MjAyNS0xMi0wMi0tMTQtMzEiLCJ3aWQiOiJnZWFyYm94VGFibGUiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,110 @@
# Ford Commercial — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:24:15.811Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /ford/pl24-entry.action
- **Method:** GET
- **Status:** 302
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/pl24-entry.action?service=fordt_parts`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/fordt_parts/vehicle.action
- **Method:** GET
- **Status:** 302
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/fordt_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 2
### /ford/web-common/css/css.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p31-g1p32-g1p33-g1p34-g1p35-g1p36-g1p37-g1p38-g1p39-g1...`
- **Yanıt özeti:**
`/*! jQuery UI - v1.9.2 - 2013-03-20 * http://jqueryui.com * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.tabs.css, jquery.ui.tooltip.css`
- **Çağrı sayısı:** 2
### /ford/web-custom/css/css.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p10-g2p11-g2p16&v=4.021.13.110`
- **Yanıt özeti:**
`span.vinHit,span.vinMiss,span.vinUnknown{padding-left:13px;background-position:left center;background-repeat:no-repeat;cursor:help}span.vinHit,span.vinMiss{font-weight:normal}span.vinHit{background-image:url("images/vin-hit.png")}span.vinMiss{background-image:url("images/vin-miss.png")}span.vinUnkno`
- **Çağrı sayısı:** 2
### /ford/js/js.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/js/js.action?idx=jg1p1-g1p2-g1p3-g1p4-g1p5-g1p6-g1p7-g1p8-g1p9-g1p10-g1p11-g1p13-g1p14-...`
- **Yanıt özeti:**
`function $C(){}$C.prototype.construct=function(){};$C.extend=function(f){var b,e,c,a,d;b=function(){if(arguments[0]!==$C){this.construct.apply(this,arguments)}};e=new this($C);c=this.prototype;for(a in f){d=f[a];if(d instanceof Function){d.$=c}e[a]=d}b.prototype=e;b.extend=this.extend;return b}; var`
- **Çağrı sayısı:** 2
### /ford/web-common/css/layout/demo.png
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/layout/demo.png`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/web-common/css/tablecontrol/tbl_header_bottom.gif
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/tablecontrol/tbl_header_bottom.gif`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/fordt_parts/json-model-config.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/fordt_parts/json-model-config.action?catCode=EX&lang=tr&modelFamily=Explorer&startup=fa...`
- **Yanıt özeti:**
`{"engineData":[{"avsCode":"_all_","catCode":"","description":"Hepsi","selected":false,"url":"vehicle.action?catCode=EX&engineAvsCode=_all_&lang=tr&modelFamily=Explorer&startup=false&mode=K00U0DEXX&upds=2026.02.11+13%3A40%3A15+CET"},{"avsCode":"ENLT0","catCode":"EX","description":"4.0 V6 OHV 12V EFI"`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/ford/pl24-entry.action?service=fordt_parts` | 302 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordt_parts/vehicle.action?mode=K00U0DEXX&lang=...` | 302 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordt_parts/vehicle.action?mode=K00U0DEXX&lang=...` | 200 | marka-ana-sayfa | `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-str` |
| GET | `https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p31-g1p32-g1p3...` | 200 | marka-ana-sayfa | `/*! jQuery UI - v1.9.2 - 2013-03-20 * http://jqueryui.com * Includes: jquery.ui.core.css, jquery.ui.` |
| GET | `https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p10-g2p11-g2p1...` | 200 | marka-ana-sayfa | `span.vinHit,span.vinMiss,span.vinUnknown{padding-left:13px;background-position:left center;backgroun` |
| GET | `https://www.partslink24.com/ford/js/js.action?idx=jg1p1-g1p2-g1p3-g1p4-g1p5-g1p6...` | 200 | marka-ana-sayfa | `function $C(){}$C.prototype.construct=function(){};$C.extend=function(f){var b,e,c,a,d;b=function(){` |
| GET | `https://www.partslink24.com/ford/js/js.action?idx=jg2p3&cmi=4.021.13.110` | 200 | marka-ana-sayfa | `function Vehicles(s){var q=null;var l=null;var p=null;var m=null;var h=null;var n=null;var d=null;va` |
| GET | `https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p51&v=4.021.13...` | 200 | marka-ana-sayfa | `*{font-family:Arial,sans-serif}table{border-collapse:separate;border-spacing:0}th{text-align:left}di` |
| GET | `https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p15&v=4.021.13...` | 200 | marka-ana-sayfa | `.vinInfoTable .attrib,.vinInfoTable .caption{width:30%}table.partinfoTable{width:100%;table-layout:f` |
| GET | `https://www.partslink24.com/ford/web-common/css/layout/demo.png` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/web-common/css/tablecontrol/tbl_header_bottom.g...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordt_parts/json-model-config.action?catCode=EX...` | 200 | marka-ana-sayfa | `{"engineData":[{"avsCode":"_all_","catCode":"","description":"Hepsi","selected":false,"url":"vehicle` |
## Notlar
- Sayfa başlığı: Ford Nutzfahrzeuge Explorer - EX (1992, 2000) - partslink24
- URL: https://www.partslink24.com/ford/fordt_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.11+13%3A40%3A15+CET
- İlk model tıklanamadı — selector bulunamadı

121
docs/pl24-catalog/ford.md Normal file
View File

@@ -0,0 +1,121 @@
# Ford — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:24:00.168Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /ford/pl24-entry.action
- **Method:** GET
- **Status:** 302
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/pl24-entry.action?service=fordp_parts`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/fordp_parts/vehicle.action
- **Method:** GET
- **Status:** 302
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/fordp_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 2
### /ford/web-common/css/css.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p31-g1p32-g1p33-g1p34-g1p35-g1p36-g1p37-g1p38-g1p39-g1...`
- **Yanıt özeti:**
`/*! jQuery UI - v1.9.2 - 2013-03-20 * http://jqueryui.com * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.tabs.css, jquery.ui.tooltip.css`
- **Çağrı sayısı:** 2
### /ford/web-custom/css/css.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p10-g2p11-g2p16&v=4.021.13.110`
- **Yanıt özeti:**
`span.vinHit,span.vinMiss,span.vinUnknown{padding-left:13px;background-position:left center;background-repeat:no-repeat;cursor:help}span.vinHit,span.vinMiss{font-weight:normal}span.vinHit{background-image:url("images/vin-hit.png")}span.vinMiss{background-image:url("images/vin-miss.png")}span.vinUnkno`
- **Çağrı sayısı:** 2
### /ford/js/js.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/js/js.action?idx=jg1p1-g1p2-g1p3-g1p4-g1p5-g1p6-g1p7-g1p8-g1p9-g1p10-g1p11-g1p13-g1p14-...`
- **Yanıt özeti:**
`function $C(){}$C.prototype.construct=function(){};$C.extend=function(f){var b,e,c,a,d;b=function(){if(arguments[0]!==$C){this.construct.apply(this,arguments)}};e=new this($C);c=this.prototype;for(a in f){d=f[a];if(d instanceof Function){d.$=c}e[a]=d}b.prototype=e;b.extend=this.extend;return b}; var`
- **Çağrı sayısı:** 2
### /ford/web-common/css/layout/demo.png
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/layout/demo.png`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /carbrands/ford/pl24_cat_logo_v2.png
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/carbrands/ford/pl24_cat_logo_v2.png`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/web-common/css/tablecontrol/tbl_header_bottom.gif
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/web-common/css/tablecontrol/tbl_header_bottom.gif`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /ford/fordp_parts/json-model-config.action
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/ford/fordp_parts/json-model-config.action?catCode=FA&lang=tr&modelFamily=Escort&startup=fals...`
- **Yanıt özeti:**
`{"engineData":[{"avsCode":"_all_","catCode":"","description":"Hepsi","selected":false,"url":"vehicle.action?catCode=FA&engineAvsCode=_all_&lang=tr&modelFamily=Escort&startup=false&mode=K00U0DEXX&upds=2026.02.11+13%3A40%3A15+CET"},{"avsCode":"ENJK0","catCode":"FA","description":"1.3L HCS EFI(60PS)","`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/ford/pl24-entry.action?service=fordp_parts` | 302 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordp_parts/vehicle.action?mode=K00U0DEXX&lang=...` | 302 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordp_parts/vehicle.action?mode=K00U0DEXX&lang=...` | 200 | marka-ana-sayfa | `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-str` |
| GET | `https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p31-g1p32-g1p3...` | 200 | marka-ana-sayfa | `/*! jQuery UI - v1.9.2 - 2013-03-20 * http://jqueryui.com * Includes: jquery.ui.core.css, jquery.ui.` |
| GET | `https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p10-g2p11-g2p1...` | 200 | marka-ana-sayfa | `span.vinHit,span.vinMiss,span.vinUnknown{padding-left:13px;background-position:left center;backgroun` |
| GET | `https://www.partslink24.com/ford/js/js.action?idx=jg1p1-g1p2-g1p3-g1p4-g1p5-g1p6...` | 200 | marka-ana-sayfa | `function $C(){}$C.prototype.construct=function(){};$C.extend=function(f){var b,e,c,a,d;b=function(){` |
| GET | `https://www.partslink24.com/ford/js/js.action?idx=jg2p3&cmi=4.021.13.110` | 200 | marka-ana-sayfa | `function Vehicles(s){var q=null;var l=null;var p=null;var m=null;var h=null;var n=null;var d=null;va` |
| GET | `https://www.partslink24.com/ford/web-common/css/css.action?idx=sg1p51&v=4.021.13...` | 200 | marka-ana-sayfa | `*{font-family:Arial,sans-serif}table{border-collapse:separate;border-spacing:0}th{text-align:left}di` |
| GET | `https://www.partslink24.com/ford/web-custom/css/css.action?idx=cg2p15&v=4.021.13...` | 200 | marka-ana-sayfa | `.vinInfoTable .attrib,.vinInfoTable .caption{width:30%}table.partinfoTable{width:100%;table-layout:f` |
| GET | `https://www.partslink24.com/ford/web-common/css/layout/demo.png` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/carbrands/ford/pl24_cat_logo_v2.png` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/web-common/css/tablecontrol/tbl_header_bottom.g...` | 200 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/ford/fordp_parts/json-model-config.action?catCode=FA...` | 200 | marka-ana-sayfa | `{"engineData":[{"avsCode":"_all_","catCode":"","description":"Hepsi","selected":false,"url":"vehicle` |
## Notlar
- Sayfa başlığı: Ford Escort - FA (1995, 2001) - partslink24
- URL: https://www.partslink24.com/ford/fordp_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.11+13%3A40%3A15+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Hyundai — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:24:31.548Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Hyundai EXCEL / PONY 89 - EUR2409200 - partslink24
- URL: https://www.partslink24.com/hyundai-kia-automotive-group/hyundai_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.05+02%3A10%3A59+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Infiniti — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:24:47.354Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Infiniti S50 - FX45/35 (EL) - partslink24
- URL: https://www.partslink24.com/nissan/infiniti_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.03+15%3A59%3A51+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Jaguar — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:25:03.100Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5jlr/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/catmeta?serviceName=jaguar_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Jaguar", "user24Brand" : "Jaguar", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3dpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVT`
- **Çağrı sayısı:** 1
### /p5jlr/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=jaguar_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Jaguar", "link" : { "wid" : "modelTable", "path" : "/p5jlr/extern/vehicle/models?lang=tr&serviceName=jaguar_parts&upds=2026-02-02--08-56" } } ], "demo" : true, "data" : { "records" : [ { "id" : "893", "link" : { "wid"`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5jlr/extern/vehicle/engines
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/vehicle/engines?lang=tr&mdl=250&serviceName=jaguar_parts&upds=2026-02-02--08-56`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Jaguar", "link" : { "wid" : "modelTable", "path" : "/p5jlr/extern/vehicle/models?lang=tr&serviceName=jaguar_parts&upds=2026-02-02--08-56", "id" : "250" } }, { "name" : "XF 2009 - 2015 (X250)", "link" : { "wid" : "engineTable"`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5jlr/extern/catmeta?serviceName=jaguar_parts&countr...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Jaguar", "user24Brand" : "Jaguar", ` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=jagu...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Jaguar", "link" : { "wid" : "modelTable", "path" : ` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=jagu...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Jaguar", "link" : { "wid" : "modelTable", "path" : ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/engines?lang=tr&mdl=250&service...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Jaguar", "link" : { "wid" : "modelTable", "path" : ` |
## Notlar
- Sayfa başlığı: Jaguar - partslink24
- URL: https://www.partslink24.com/pl24-app/jaguar_parts/0/eyJwYXRoIjoiL3A1amxyL2V4dGVybi92ZWhpY2xlL2VuZ2luZXM%252FbGFuZz10ciZtZGw9MjUwJnNlcnZpY2VOYW1lPWphZ3Vhcl9wYXJ0cyZ1cGRzPTIwMjYtMDItMDItLTA4LTU2Iiwid2lkIjoiZW5naW5lVGFibGUifQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

20
docs/pl24-catalog/kia.md Normal file
View File

@@ -0,0 +1,20 @@
# Kia — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:25:18.710Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Kia RETONA 99 - GECKFK000A - partslink24
- URL: https://www.partslink24.com/hyundai-kia-automotive-group/kia_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.05+02%3A10%3A59+CET
- İlk model tıklanamadı — selector bulunamadı

85
docs/pl24-catalog/koda.md Normal file
View File

@@ -0,0 +1,85 @@
# Škoda — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:30:29.799Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=skoda_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Škoda", "user24Brand" : "Skoda", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAG1BMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABp4cHsAAAACHRSTlMAIENjh6bG8KJiM+YAAANkSURBVHja7drbbuowEEDRGd9m/v+Lz5EoATo2Q9Qa+rCX+lRZhOw4iRMhAAAAAA`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=skoda_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Škoda", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=skoda_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ { "id" : "9`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=65232&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Škoda", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=skoda_parts&upds=2026-02-13--00-01", "id" : "65232_5_null" } }, { "name" : "Kamiq", "link" : {`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=skoda_parts&countr...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Škoda", "user24Brand" : "Skoda", ` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Škoda", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Škoda", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=65232&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Škoda", "link" : { "wid" : "modelFamiliesTable", "p` |
## Notlar
- Sayfa başlığı: Škoda - partslink24
- URL: https://www.partslink24.com/pl24-app/skoda_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT02NTIzMiZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9NSZzZXJ2aWNlTmFtZT1za29kYV9wYXJ0cyZ1cGRzPTIwMjYtMDItMTMtLTAwLTAxIiwid2lkIjoibW9kZWxZZWFyVGFibGUifQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Land Rover — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:25:34.471Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5jlr/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/catmeta?serviceName=landrover_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Land Rover", "user24Brand" : "LandRover", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAKlBMVEVHcEwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwIHiwQ3LidAAAADXRSTlMADiA1SmF1j6a70OPz4w6I1AAADn9JREFUeNrs1U9v0mAcB/AfbC+gK`
- **Çağrı sayısı:** 1
### /p5jlr/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=landrover_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Land Rover", "link" : { "wid" : "modelTable", "path" : "/p5jlr/extern/vehicle/models?lang=tr&serviceName=landrover_parts&upds=2026-02-02--08-56" } } ], "demo" : true, "data" : { "records" : [ { "id" : "17", "link" : { `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5jlr/extern/vehicle/engines
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5jlr/extern/vehicle/engines?lang=tr&mdl=24&serviceName=landrover_parts&upds=2026-02-02--08-...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Land Rover", "link" : { "wid" : "modelTable", "path" : "/p5jlr/extern/vehicle/models?lang=tr&serviceName=landrover_parts&upds=2026-02-02--08-56", "id" : "24" } }, { "name" : "RANGE ROVER EVOQUE 2012 - 2018 (L538)", "link" : { `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5jlr/extern/catmeta?serviceName=landrover_parts&cou...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Land Rover", "user24Brand" : "LandRover` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=land...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Land Rover", "link" : { "wid" : "modelTable", "path` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/models?lang=tr&serviceName=land...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Land Rover", "link" : { "wid" : "modelTable", "path` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5jlr/extern/vehicle/engines?lang=tr&mdl=24&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Land Rover", "link" : { "wid" : "modelTable", "path` |
## Notlar
- Sayfa başlığı: Land Rover - partslink24
- URL: https://www.partslink24.com/pl24-app/landrover_parts/0/eyJwYXRoIjoiL3A1amxyL2V4dGVybi92ZWhpY2xlL2VuZ2luZXM%252FbGFuZz10ciZtZGw9MjQmc2VydmljZU5hbWU9bGFuZHJvdmVyX3BhcnRzJnVwZHM9MjAyNi0wMi0wMi0tMDgtNTYiLCJ3aWQiOiJlbmdpbmVUYWJsZSJ9/
- İlk model tıklanamadı — selector bulunamadı

129
docs/pl24-catalog/lexus.md Normal file
View File

@@ -0,0 +1,129 @@
# Lexus — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:25:49.873Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5toyota/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/catmeta?serviceName=lexus_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Lexus", "user24Brand" : "Lexus", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAHlBMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABaVcReAAAACXRSTlMAESNLeJO01eypTF87AAAFb0lEQVR42u3c23KjOhCFYakPkvr9X3hnZ6YMBiwDcjwp83+TuUiCXWSl1R`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/modelFamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?lang=tr&serviceName=lexus_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41" } } ], "demo" : true, "data" : { "records" : [ { "id" : "64"`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/models?allMarkets=false&family=76&lang=tr&serviceName=lexus_parts&up...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41", "id" : "76" } }, { "name" : "LEXUS NX", "link" : { "w`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr1?allMarkets=false&family=76&lang=tr&mainModelCode=527220&servi...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41", "id" : "76" } }, { "name" : "LEXUS NX", "link" : { "w`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr2?allMarkets=false&family=76&lang=tr&mainModelCode=527220&restr...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41", "id" : "76" } }, { "name" : "LEXUS NX", "link" : { "w`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr3?allMarkets=false&family=76&lang=tr&mainModelCode=527220&restr...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41", "id" : "76" } }, { "name" : "LEXUS NX", "link" : { "w`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/modelCodes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/modelCodes?allMarkets=false&family=76&lang=tr&mainModelCode=527220&r...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=lexus_parts&upds=2026-01-30--08-41", "id" : "76" } }, { "name" : "LEXUS NX", "link" : { "w`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5toyota/extern/catmeta?serviceName=lexus_parts&coun...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Lexus", "user24Brand" : "Lexus", ` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?lang=tr&servic...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?allMarkets=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/models?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr1?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr2?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr3?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelCodes?allMarkets=false&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Lexus", "link" : { "wid" : "modelFamiliesTable", "p` |
## Notlar
- Sayfa başlığı: Lexus, LEXUS NX, LEXUS NX200/250/260/350/3... - partslink24
- URL: https://www.partslink24.com/pl24-app/lexus_parts/0/eyJwYXRoIjoiL3A1dG95b3RhL2V4dGVybi92ZWhpY2xlL21vZGVsQ29kZXM%252FYWxsTWFya2V0cz1mYWxzZSZmYW1pbHk9NzYmbGFuZz10ciZtYWluTW9kZWxDb2RlPTUyNzIyMCZyZXN0cjE9X2FyYml0cmFyeV8mcmVzdHIyPV9hcmJpdHJhcnlfJnJlc3RyMz1fYXJiaXRyYXJ5XyZzZXJ2aWNlTmFtZT1sZXh1c19wYXJ0cyZ1cGRzPTIwMjYtMDEtMzAtLTA4LTQxIiwid2lkIjoibW9kZWxDb2Rlc1RhYmxlIiwiYXV0byI6dHJ1ZX0%253D/
- İlk model tıklanamadı — selector bulunamadı

84
docs/pl24-catalog/man.md Normal file
View File

@@ -0,0 +1,84 @@
# MAN — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:26:05.331Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5man/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5man/extern/catmeta?serviceName=man_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "MAN", "user24Brand" : "MAN", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAGFBMVEVHcEwdHRsdHRsdHRsdHRsdHRsdHRsdHRsMQBB6AAAAB3RSTlMAFjxmj7viWSteHAAABqBJREFUeNrs17132jAQAPCzDZn9SIAVkias5IOyQpNUK5RQryVt7Ll8SP9+t+S9XrBkSXcs91`
- **Çağrı sayısı:** 1
### /p5man/extern/model/categories
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5man/extern/model/categories?lang=tr&serviceName=man_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MAN", "link" : { "wid" : "categoriesTable", "path" : "/p5man/extern/model/categories?lang=tr&serviceName=man_parts" } } ], "demo" : true, "data" : { "records" : [ { "id" : "l", "link" : { "wid" : "categoryTypesTable",`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5man/extern/model/categoryTypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5man/extern/model/categoryTypes?category=l&lang=tr&serviceName=man_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MAN", "link" : { "wid" : "categoriesTable", "path" : "/p5man/extern/model/categories?lang=tr&serviceName=man_parts", "id" : "l" } }, { "name" : "Kamyon", "link" : { "wid" : "categoryTypesTable", "path" : "/p5man/extern/`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5man/extern/catmeta?serviceName=man_parts&country=D...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "MAN", "user24Brand" : "MAN", "log` |
| GET | `https://www.partslink24.com/p5man/extern/model/categories?lang=tr&serviceName=ma...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MAN", "link" : { "wid" : "categoriesTable", "path" ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5man/extern/model/categoryTypes?category=l&lang=tr&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MAN", "link" : { "wid" : "categoriesTable", "path" ` |
## Notlar
- Sayfa başlığı: MAN - partslink24
- URL: https://www.partslink24.com/pl24-app/man_parts/0/eyJwYXRoIjoiL3A1bWFuL2V4dGVybi9tb2RlbC9jYXRlZ29yeVR5cGVzP2NhdGVnb3J5PWwmbGFuZz10ciZzZXJ2aWNlTmFtZT1tYW5fcGFydHMiLCJ3aWQiOiJjYXRlZ29yeVR5cGVzVGFibGUifQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,95 @@
# Mercedes-Benz Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:26:36.147Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /p5daimler/extern/entry
- **Method:** GET
- **Status:** 302
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/entry?richParams=mercedesclassic_parts`
- **Yanıt özeti:**
`(yanıt yok)`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?lang=de&serviceName=mercedesclassic_parts&_=1771939596441`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Classic", "user24Brand" : "Mercedes", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAJ1BMVEVHcEwJCAcLCQgMCwkMCwkLCggLCggLCggKCQgKCQgKCQgXFA8DAwSI8k3qAAAAC3RSTlMAEChDXXSMpsHY7eEdM+0AAAvXSURBVHja7NntiqwwDAbgfLR`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=de&serviceName=mercedesclassic_parts&_=1771939596442`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=de&serviceName=mercedesclassic_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/modeltype
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggregatesVisible=false&blockPresel=false&lan...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=de&serviceName=mercedesclassic_parts&upds=ND", "id" : "P-F" } }, { "name" : "PKW", "li`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/model
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregatesVisible=false&blockPresel=false&lang=de...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=de&serviceName=mercedesclassic_parts&upds=ND", "id" : "P-F" } }, { "name" : "PKW", "li`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/p5daimler/extern/entry?richParams=mercedesclassic_pa...` | 302 | marka-ana-sayfa | `` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/t...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/jquery/1.0.17/assets/locales/e...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?lang=de&serviceName=mercede...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Classic", "user24Brand" :` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=de&serviceName=m...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggre...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregate...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Classic", "link" : { "wid" : "scopeTable", ` |
## Notlar
- Sayfa başlığı: Mercedes-Benz Classic, PKW, C107 partslink24
- URL: https://www.partslink24.com/p5/latest/p5.html#%2Fp5daimler~mercedesclassic_parts~de~~~~~eyJwIjoidmVoaWNsZXMiLCJiIjoiL3A1ZGFpbWxlci9leHRlcm4vdmVoaWNsZS8iLCJlcCI6WyJsYW5nPWRlIiwic2VydmljZU5hbWU9bWVyY2VkZXNjbGFzc2ljX3BhcnRzIiwiYWdnVHlwZUlkPUYiLCJhZ2dyZWdhdGVzVmlzaWJsZT1mYWxzZSIsImJsb2NrUHJlc2VsPWZhbHNlIiwicHJvZHVjdENsYXNzSWQ9UCIsInVwZHM9TkQiLCJtb2RlbFR5cGU9QzEwNyJdLCJ3cyI6W3sid2lkIjoic2NvcGVUYWJsZSIsInBhdGgiOiJzY29wZSIsImlkIjoiUC1GIiwiZXAiOlswLDFdfSx7IndpZCI6Im1vZGVsVHlwZVRhYmxlIiwicGF0aCI6Im1vZGVsdHlwZSIsImlkIjoiQzEwNyIsImVwIjpbMiwzLDQsMCw1LDEsNl19LHsid2lkIjoibW9kZWxUYWJsZSIsInBhdGgiOiJtb2RlbCIsImVwIjpbMiwzLDQsMCw3LDUsMSw2XX1dfQ%3D%3D
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,107 @@
# Mercedes-Benz Trucks — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:26:51.705Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedestrucks_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Trucks", "user24Brand" : "MercedesTrucks", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAA51BMVEVHcEz4+fk5Ozv///8nKyv///8fISCdoqT///8dHhz///+fo6X6+/shIyIeHh3w8fGgpaceIB/e4OAeHx4eIB/P0tOboKIeHx6xtbfIyswdHRuMkp`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=mercedestrucks_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedestrucks_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [ {`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/modeltype
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedestrucks_parts&upds=ND", "id" : "L-F" } }, { "name" : "Ağır vasıta", `
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/model
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang=tr&...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedestrucks_parts&upds=ND", "id" : "L-F" } }, { "name" : "Ağır vasıta", `
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/modelcatalog
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/modelcatalog?aggTypeId=F&aggregatesVisible=false&blockPresel=true&l...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedestrucks_parts&upds=ND", "id" : "L-F" } }, { "name" : "Ağır vasıta", `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedestrucks_...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Trucks", "user24Brand" : ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=m...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?aggregatesVisible=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggre...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregate...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/modelcatalog?aggTypeId=F&ag...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Trucks", "link" : { "wid" : "scopeTable", ` |
## Notlar
- Sayfa başlığı: Mercedes-Benz Trucks, Ağır vasıta, C938 - partslink24
- URL: https://www.partslink24.com/pl24-app/mercedestrucks_parts/0/eyJwYXRoIjoiL3A1ZGFpbWxlci9leHRlcm4vdmVoaWNsZS9tb2RlbGNhdGFsb2c%252FYWdnVHlwZUlkPUYmYWdncmVnYXRlc1Zpc2libGU9ZmFsc2UmYmxvY2tQcmVzZWw9dHJ1ZSZsYW5nPXRyJm1vZGVsQ29kZT1DOTM4MTQyJm1vZGVsVHlwZT1DOTM4JnByb2R1Y3RDbGFzc0lkPUwmc2VydmljZU5hbWU9bWVyY2VkZXN0cnVja3NfcGFydHMmdXBkcz1ORCIsIndpZCI6Im1vZGVsQ2F0YWxvZ1RhYmxlIiwiYXV0byI6dHJ1ZX0%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,74 @@
# Mercedes-Benz Unimog — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:27:07.433Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedesunimog_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Unimog", "user24Brand" : "MercedesUnimog", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=mercedesunimog_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Unimog", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedesunimog_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [ {`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedesunimog_...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Unimog", "user24Brand" : ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=m...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Unimog", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?aggregatesVisible=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Unimog", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
## Notlar
- Sayfa başlığı: partslink24
- URL: https://www.partslink24.com/pl24-app/mercedesunimog_parts/0/0?desktop=true&lang=tr
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,96 @@
# Mercedes-Benz Vans — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:27:23.044Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedesvans_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Vans", "user24Brand" : "MercedesVans", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAJFBMVEVHcEwKCQcJCAcKCQgLCggGBgUIBwcJCAcJCAcIBwYDAwQXFA+M6EceAAAACnRSTlMAmRG5Q+t4W9QnSJ6llQAACoxJREFUeNrs2NuSnEAIBmAODTS8/w`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=mercedesvans_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedesvans_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [ { `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/modeltype
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedesvans_parts&upds=ND", "id" : "T-F" } }, { "name" : "Panelvan", "lin`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/model
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang=tr&...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedesvans_parts&upds=ND", "id" : "T-F" } }, { "name" : "Panelvan", "lin`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedesvans_pa...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz Vans", "user24Brand" : "M` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=m...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?aggregatesVisible=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggre...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregate...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz Vans", "link" : { "wid" : "scopeTable", ` |
## Notlar
- Sayfa başlığı: Mercedes-Benz Vans, Panelvan - partslink24
- URL: https://www.partslink24.com/pl24-app/mercedesvans_parts/0/eyJwYXRoIjoiL3A1ZGFpbWxlci9leHRlcm4vdmVoaWNsZS9tb2RlbD9hZ2dUeXBlSWQ9RiZhZ2dyZWdhdGVzVmlzaWJsZT1mYWxzZSZibG9ja1ByZXNlbD10cnVlJmxhbmc9dHImbW9kZWxUeXBlPUM0MTUmcHJvZHVjdENsYXNzSWQ9VCZzZXJ2aWNlTmFtZT1tZXJjZWRlc3ZhbnNfcGFydHMmdXBkcz1ORCIsIndpZCI6Im1vZGVsVGFibGUiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,74 @@
# Mercedes-Benz — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:26:20.762Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedes_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz", "user24Brand" : "Mercedes", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAIVBMVEVHcEwDAwQDAwQDAwQDAwQDAwQDAwQDAwQDAwQDAwQDAwQ7c86cAAAACnRSTlMADh82UG6RstHsDX9HfAAADAFJREFUeNrsmMtv00AQxiePPk+RUCniZAmJR08RolL`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=mercedes_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mercedes-Benz", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=mercedes_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [ { "id" :`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=mercedes_parts&...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mercedes-Benz", "user24Brand" : "Merced` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=m...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz", "link" : { "wid" : "scopeTable", "p` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?aggregatesVisible=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mercedes-Benz", "link" : { "wid" : "scopeTable", "p` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
## Notlar
- Sayfa başlığı: partslink24
- URL: https://www.partslink24.com/pl24-app/mercedes_parts/0/0?desktop=true&lang=tr
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,118 @@
# MINI Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:27:53.951Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=miniclassic_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "MINI Classic", "user24Brand" : "Mini", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAACdQTFRFR3BMISEfISEhIiIhIiIgISEgIiIhIiIgIiIhIiIhIiIgIiIhIiIhbtAtwAAAAAx0Uk5TABQxSFZxiKK6zd7v5iEg/gAACjtJREFUeNrt282PG+UB`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "MINI", "link" : { `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=MINI&serviceName=miniclassic_parts&upds=2026-02-...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=MINI&modelType=R50&serviceName=miniclassic_pa...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=MINI&modelType=R50&res1=HC&serviceName=minicl...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=MINI&modelType=R50&res1=HC&res2=Cooper&servic...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=miniclassic_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=miniclassic_parts&c...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "MINI Classic", "user24Brand" : "Mini", ` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=MINI&ser...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI Classic", "link" : { "wid" : "modelTable", "pa` |
## Notlar
- Sayfa başlığı: MINI Classic, MINI, R50 - partslink24
- URL: https://www.partslink24.com/pl24-app/miniclassic_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9TUlOSSZtb2RlbFR5cGU9UjUwJnJlczE9SEMmcmVzMj1Db29wZXImc2VydmljZU5hbWU9bWluaWNsYXNzaWNfcGFydHMmdXBkcz0yMDI2LTAyLTEwLS0xNC0yMSIsIndpZCI6InJlc3RyaWN0aW9uVGFibGUzIiwiYXV0byI6dHJ1ZX0%253D/
- İlk model tıklanamadı — selector bulunamadı

118
docs/pl24-catalog/mini.md Normal file
View File

@@ -0,0 +1,118 @@
# MINI — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:27:38.616Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5bmw/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=mini_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "MINI", "user24Brand" : "Mini", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAAB5QTFRFR3BMICAgIyAgJCAgIiAgJCAgIx4gIx8gIx8gIx8gU7wfegAAAAl0Uk5TABAqQGeBpsPsgSO3OwAABR1JREFUeNrt3Ltv21YYBfBPr9jeBKSNnY2A0zbaVD/a`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts&upds=2026-02-10--14-21" } } ], "demo" : true, "data" : { "records" : [ { "id" : "MINI", "link" : { "wid" : `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/modeltypes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=MINI&serviceName=mini_parts&upds=2026-02-10--14-...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", "path" : `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=MINI&modelType=R50&serviceName=mini_parts&upd...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", "path" : `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=MINI&modelType=R50&res1=HC&serviceName=mini_p...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", "path" : `
- **Çağrı sayısı:** 1
### /p5bmw/extern/vehicle/restrictions3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=MINI&modelType=R50&res1=HC&res2=Cooper&servic...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini_parts&upds=2026-02-10--14-21", "id" : "MINI" } }, { "name" : "MINI", "link" : { "wid" : "modelTypeTable", "path" : `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5bmw/extern/catmeta?serviceName=mini_parts&country=...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "MINI", "user24Brand" : "Mini", "l` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/models?lang=tr&serviceName=mini...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/modeltypes?lang=tr&mdl=MINI&ser...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions1?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions2?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
| GET | `https://www.partslink24.com/p5bmw/extern/vehicle/restrictions3?lang=tr&mdl=MINI&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "MINI", "link" : { "wid" : "modelTable", "path" : "/` |
## Notlar
- Sayfa başlığı: MINI, MINI, R50 - partslink24
- URL: https://www.partslink24.com/pl24-app/mini_parts/0/eyJwYXRoIjoiL3A1Ym13L2V4dGVybi92ZWhpY2xlL3Jlc3RyaWN0aW9uczM%252FbGFuZz10ciZtZGw9TUlOSSZtb2RlbFR5cGU9UjUwJnJlczE9SEMmcmVzMj1Db29wZXImc2VydmljZU5hbWU9bWluaV9wYXJ0cyZ1cGRzPTIwMjYtMDItMTAtLTE0LTIxIiwid2lkIjoicmVzdHJpY3Rpb25UYWJsZTMiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,107 @@
# Mitsubishi — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:28:09.554Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5mitsubishi/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5mitsubishi/extern/catmeta?serviceName=mmc_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Mitsubishi", "user24Brand" : "Mitsubishi", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAOVBMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAbAAAAAAAAAABDAADtAADtAABcAADtAADtAADtAADtAAAAAAC2aW4/AAAAEXRSTlMAv1Cl8Ic9JddoFOFwCEOXv/bxoKgAAA1L`
- **Çağrı sayısı:** 1
### /p5mitsubishi/extern/vehicles/vehiclesOverview
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=tr&serviceName=mmc_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", "path" : "/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS" } } ], "demo" : true, "data" : { "records" : [ { "id" : "43", `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5mitsubishi/extern/vehicles/vehicles
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5mitsubishi/extern/vehicles/vehicles?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS&vehic...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", "path" : "/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS", "id" : "55" } }, { "name" : "COLT<CABRIOLET>(EUR/PF)", "link" : { `
- **Çağrı sayısı:** 1
### /p5mitsubishi/extern/vehicles/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5mitsubishi/extern/vehicles/models?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS&vehicle...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", "path" : "/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS", "id" : "55" } }, { "name" : "COLT<CABRIOLET>(EUR/PF)", "link" : { `
- **Çağrı sayısı:** 1
### /p5mitsubishi/extern/vehicles/classifications
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5mitsubishi/extern/vehicles/classifications?lang=tr&modelId=Z37A&serviceName=mmc_parts&upds...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", "path" : "/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=tr&serviceName=mmc_parts&upds=SYSPROPS_UPDS", "id" : "55" } }, { "name" : "COLT<CABRIOLET>(EUR/PF)", "link" : { `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/catmeta?serviceName=mmc_parts&co...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Mitsubishi", "user24Brand" : "Mitsubish` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=t...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", ` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/vehicles/vehiclesOverview?lang=t...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/vehicles/vehicles?lang=tr&servic...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", ` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/vehicles/models?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", ` |
| GET | `https://www.partslink24.com/p5mitsubishi/extern/vehicles/classifications?lang=tr...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Mitsubishi", "link" : { "wid" : "vehiclesOverviewTable", ` |
## Notlar
- Sayfa başlığı: Mitsubishi, COLT<CABRIOLET>(EUR/PF), Z30# - partslink24
- URL: https://www.partslink24.com/pl24-app/mmc_parts/0/eyJwYXRoIjoiL3A1bWl0c3ViaXNoaS9leHRlcm4vdmVoaWNsZXMvY2xhc3NpZmljYXRpb25zP2xhbmc9dHImbW9kZWxJZD1aMzdBJnNlcnZpY2VOYW1lPW1tY19wYXJ0cyZ1cGRzPVNZU1BST1BTX1VQRFMmdmVoaWNsZT1DNjAxSDYwOEQmdmVoaWNsZU92ZXJ2aWV3PTU1Iiwid2lkIjoiY2xhc3NpZmljYXRpb25zVGFibGUiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Nissan — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:28:24.924Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Nissan TK3 - ATLEON (EL) - partslink24
- URL: https://www.partslink24.com/nissan/nissan_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.03+15%3A59%3A51+CET
- İlk model tıklanamadı — selector bulunamadı

20
docs/pl24-catalog/opel.md Normal file
View File

@@ -0,0 +1,20 @@
# Opel — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:28:40.611Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Opel - partslink24
- URL: https://www.partslink24.com/opel/opel_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.21+07%3A11%3A24+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Peugeot — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:28:56.262Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Peugeot 405 - partslink24
- URL: https://www.partslink24.com/psa/peugeot_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2024.02.13+09%3A27%3A21+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Polestar — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:29:12.071Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Polestar - partslink24
- URL: https://www.partslink24.com/volvo/polestar_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.19+14%3A46%3A42
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Porsche Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:29:43.212Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=porscheclassic_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Porsche Classic", "user24Brand" : "PorscheClassic", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAABDlBMVEUAAAA0MjMDAwQrKCc4My4nIh4DAwQDAwQDAwQDAwQDAwQ0MjMDAwRxYEU1MjIoJic0MjM1MjI0MjMsKCbJp2U0MjM0MjPJo1g0MjPyz4XRs3I0MjM0MjP`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=porscheclassic_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Porsche Classic", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=porscheclassic_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=64449&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Porsche Classic", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=porscheclassic_parts&upds=2026-02-13--00-01", "id" : "64449_61_null" } }, { "name" : "Po`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=porscheclassic_par...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Porsche Classic", "user24Brand" : "Pors` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche Classic", "link" : { "wid" : "modelFamiliesTable"` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche Classic", "link" : { "wid" : "modelFamiliesTable"` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=64449&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche Classic", "link" : { "wid" : "modelFamiliesTable"` |
## Notlar
- Sayfa başlığı: Porsche Classic - partslink24
- URL: https://www.partslink24.com/pl24-app/porscheclassic_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT02NDQ0OSZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9NjEmc2VydmljZU5hbWU9cG9yc2NoZWNsYXNzaWNfcGFydHMmdXBkcz0yMDI2LTAyLTEzLS0wMC0wMSIsIndpZCI6Im1vZGVsWWVhclRhYmxlIn0%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Porsche — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:29:27.739Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=porsche_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Porsche", "user24Brand" : "Porsche", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAAv1QTFRFAAAAAAAAAAAAAAAANygOAAAAEw4IAAAAAAAAAAAA+Pj49vb2+Pj48vLv8O3n9PT08Orc7eXM9+6k592e2c2a5eTgysjFwcHAzMvM7Ozs8/Hk2sqizr`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=porsche_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Porsche", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=porsche_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ { "id" `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=85399&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Porsche", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=porsche_parts&upds=2026-02-13--00-01", "id" : "85399_6_null" } }, { "name" : "Porsche 992 GT3/RS`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=porsche_parts&coun...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Porsche", "user24Brand" : "Porsche", ` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche", "link" : { "wid" : "modelFamiliesTable", ` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche", "link" : { "wid" : "modelFamiliesTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=85399&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Porsche", "link" : { "wid" : "modelFamiliesTable", ` |
## Notlar
- Sayfa başlığı: Porsche - partslink24
- URL: https://www.partslink24.com/pl24-app/porsche_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT04NTM5OSZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9NiZzZXJ2aWNlTmFtZT1wb3JzY2hlX3BhcnRzJnVwZHM9MjAyNi0wMi0xMy0tMDAtMDEiLCJ3aWQiOiJtb2RlbFllYXJUYWJsZSJ9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,107 @@
# Renault — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:29:58.625Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5renault/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/catmeta?serviceName=renault_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Renault", "user24Brand" : "Renault", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAABtQTFRFR3BMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaeHB7AAAAAh0Uk5TABdAYoKgwOl1MHDiAAAGVElEQVR42u2d0W6jMBREYzDY///FK62iVbslyZ0mI6`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/catalogs
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=renault_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=renault_parts&upds=2025-12-02--14-31" } } ], "demo" : true, "data" : { "records" : [ { "id" : "X55", "description" `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/models?catalog=X53&lang=tr&serviceName=renault_parts&upds=2025-12-0...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=renault_parts&upds=2025-12-02--14-31", "id" : "X53" } }, { "name" : "RENAULT 19", "link" : { "wid" : "modelTable", `
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/engines
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/engines?catalog=X53&lang=tr&model=B53&serviceName=renault_parts&upd...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=renault_parts&upds=2025-12-02--14-31", "id" : "X53" } }, { "name" : "RENAULT 19", "link" : { "wid" : "modelTable", `
- **Çağrı sayısı:** 1
### /p5renault/extern/vehicle/gearbox
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5renault/extern/vehicle/gearbox?catalog=X53&engineFamily=CXX&engineIndex=730&engineLevel=M0...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path" : "/p5renault/extern/vehicle/catalogs?lang=tr&serviceName=renault_parts&upds=2025-12-02--14-31", "id" : "X53" } }, { "name" : "RENAULT 19", "link" : { "wid" : "modelTable", `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5renault/extern/catmeta?serviceName=renault_parts&c...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Renault", "user24Brand" : "Renault", ` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path"` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/catalogs?lang=tr&serviceNam...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path"` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/models?catalog=X53&lang=tr&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path"` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/engines?catalog=X53&lang=tr...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path"` |
| GET | `https://www.partslink24.com/p5renault/extern/vehicle/gearbox?catalog=X53&engineF...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Renault", "link" : { "wid" : "catalogTable", "path"` |
## Notlar
- Sayfa başlığı: Renault, RENAULT 19, 5 KAPILI SEDAN - partslink24
- URL: https://www.partslink24.com/pl24-app/renault_parts/0/eyJwYXRoIjoiL3A1cmVuYXVsdC9leHRlcm4vdmVoaWNsZS9nZWFyYm94P2NhdGFsb2c9WDUzJmVuZ2luZUZhbWlseT1DWFgmZW5naW5lSW5kZXg9NzMwJmVuZ2luZUxldmVsPU0wJmVuZ2luZVR5cGU9QzFHJmxhbmc9dHImbW9kZWw9QjUzJnNlcnZpY2VOYW1lPXJlbmF1bHRfcGFydHMmdXBkcz0yMDI1LTEyLTAyLS0xNC0zMSIsIndpZCI6ImdlYXJib3hUYWJsZSIsImF1dG8iOnRydWV9/
- İlk model tıklanamadı — selector bulunamadı

85
docs/pl24-catalog/seat.md Normal file
View File

@@ -0,0 +1,85 @@
# SEAT — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:30:14.062Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=seat_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "SEAT", "user24Brand" : "Seat", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAABtQTFRFR3BMAAAAAAAAAAAAAAAAAQEBAAAAAAAAAAAA3Ag5fQAAAAh0Uk5TABdAfJmwwuB6NPDJAAAE50lEQVR42u3cQU8iSRTA8dfNDPHYYTcTj01x4Wi6kOHoDsnE`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=seat_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "SEAT", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=seat_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ { "id" : "873`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=87368&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "SEAT", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=seat_parts&upds=2026-02-13--00-01", "id" : "87368_4_null" } }, { "name" : "Cordoba (SEAT)", "li`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=seat_parts&country...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "SEAT", "user24Brand" : "Seat", "l` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "SEAT", "link" : { "wid" : "modelFamiliesTable", "pa` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "SEAT", "link" : { "wid" : "modelFamiliesTable", "pa` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=87368&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "SEAT", "link" : { "wid" : "modelFamiliesTable", "pa` |
## Notlar
- Sayfa başlığı: SEAT - partslink24
- URL: https://www.partslink24.com/pl24-app/seat_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT04NzM2OCZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9NCZzZXJ2aWNlTmFtZT1zZWF0X3BhcnRzJnVwZHM9MjAyNi0wMi0xMy0tMDAtMDEiLCJ3aWQiOiJtb2RlbFllYXJUYWJsZSJ9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,96 @@
# smart — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:30:45.180Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5daimler/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=smart_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "smart", "user24Brand" : "Smart", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAABaFBMVEVHcEyzsrKSkZGzsrLAv8DAv7/Gv7HdoQ3u7/Hy8vPh4ePp6evNzM2zsrK1tLSzsrKzs7OVlJSmpaW0s7PVmgHCwsP3ugT765vkqwyzsrKzsrPz8/Senp6Li4v09PTy8vPR0dLpui`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/scope
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=smart_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=smart_parts&upds=ND" } } ], "demo" : true, "data" : { "records" : [ { "id" : "F-F", `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/modeltype
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=smart_parts&upds=ND", "id" : "F-F" } }, { "name" : "Smart", "link" : { "wid" : "m`
- **Çağrı sayısı:** 1
### /p5daimler/extern/vehicle/model
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregatesVisible=false&blockPresel=true&lang=tr&...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "/p5daimler/extern/vehicle/scope?aggregatesVisible=false&blockPresel=true&lang=tr&serviceName=smart_parts&upds=ND", "id" : "F-F" } }, { "name" : "Smart", "link" : { "wid" : "m`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5daimler/extern/catmeta?serviceName=smart_parts&cou...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "smart", "user24Brand" : "Smart", ` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?lang=tr&serviceName=s...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/scope?aggregatesVisible=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/modeltype?aggTypeId=F&aggre...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "` |
| GET | `https://www.partslink24.com/p5daimler/extern/vehicle/model?aggTypeId=F&aggregate...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "smart", "link" : { "wid" : "scopeTable", "path" : "` |
## Notlar
- Sayfa başlığı: smart, Smart - partslink24
- URL: https://www.partslink24.com/pl24-app/smart_parts/0/eyJwYXRoIjoiL3A1ZGFpbWxlci9leHRlcm4vdmVoaWNsZS9tb2RlbD9hZ2dUeXBlSWQ9RiZhZ2dyZWdhdGVzVmlzaWJsZT1mYWxzZSZibG9ja1ByZXNlbD10cnVlJmxhbmc9dHImbW9kZWxUeXBlPUM0NTImcHJvZHVjdENsYXNzSWQ9RiZzZXJ2aWNlTmFtZT1zbWFydF9wYXJ0cyZ1cGRzPU5EIiwid2lkIjoibW9kZWxUYWJsZSIsImF1dG8iOnRydWV9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,96 @@
# Suzuki — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:31:00.743Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5suzuki/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5suzuki/extern/catmeta?serviceName=suzuki_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Suzuki", "user24Brand" : "Suzuki", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVT`
- **Çağrı sayısı:** 1
### /p5suzuki/extern/vehicle/modelFamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5suzuki/extern/vehicle/modelFamilies?lang=tr&serviceName=suzuki_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5suzuki/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=suzuki_parts&upds=2026-02-18--14-38" } } ], "demo" : true, "data" : { "records" : [ { "id" : "A`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5suzuki/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5suzuki/extern/vehicle/models?allMarkets=false&family=SWIFT&lang=tr&serviceName=suzuki_part...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5suzuki/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=suzuki_parts&upds=2026-02-18--14-38", "id" : "SWIFT" } }, { "name" : "SWIFT", "link" : { `
- **Çağrı sayısı:** 1
### /p5suzuki/extern/vehicle/restr1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5suzuki/extern/vehicle/restr1?allMarkets=false&dateFrom=200404&dateTo=200811&family=SWIFT&l...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5suzuki/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=suzuki_parts&upds=2026-02-18--14-38", "id" : "SWIFT" } }, { "name" : "SWIFT", "link" : { `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5suzuki/extern/catmeta?serviceName=suzuki_parts&cou...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Suzuki", "user24Brand" : "Suzuki", ` |
| GET | `https://www.partslink24.com/p5suzuki/extern/vehicle/modelFamilies?lang=tr&servic...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5suzuki/extern/vehicle/modelFamilies?allMarkets=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5suzuki/extern/vehicle/models?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5suzuki/extern/vehicle/restr1?allMarkets=false&date...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Suzuki", "link" : { "wid" : "modelFamiliesTable", "` |
## Notlar
- Sayfa başlığı: Suzuki, SWIFT - partslink24
- URL: https://www.partslink24.com/pl24-app/suzuki_parts/0/eyJwYXRoIjoiL3A1c3V6dWtpL2V4dGVybi92ZWhpY2xlL3Jlc3RyMT9hbGxNYXJrZXRzPWZhbHNlJmRhdGVGcm9tPTIwMDQwNCZkYXRlVG89MjAwODExJmZhbWlseT1TV0lGVCZsYW5nPXRyJm1haW5Nb2RlbENvZGU9UlM0MTNfUDIyJnNlcnZpY2VOYW1lPXN1enVraV9wYXJ0cyZ1cGRzPTIwMjYtMDItMTgtLTE0LTM4Iiwid2lkIjoiY2hhcmFjdGVyaXN0aWMxVGFibGUiLCJhdXRvIjp0cnVlfQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

129
docs/pl24-catalog/toyota.md Normal file
View File

@@ -0,0 +1,129 @@
# Toyota — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:31:16.362Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5toyota/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/catmeta?serviceName=toyota_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Toyota", "user24Brand" : "Toyota", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAHlBMVEVHcEwjIywjIywjIywjIywjIywjIywjIywjIywjIyyuO+lqAAAACXRSTlMAGztefZq61u5F891tAAAIf0lEQVR42u2cS1PbSBDHx5gNzk1AdhPfBGQ34aYQqA03VxKy8c0mWQg3`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/modelFamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?lang=tr&serviceName=toyota_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41" } } ], "demo" : true, "data" : { "records" : [ { "id" : "1`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/models
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/models?allMarkets=false&family=31&lang=tr&serviceName=toyota_parts&u...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41", "id" : "31" } }, { "name" : "COROLLA", "link" : { "`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr1
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr1?allMarkets=false&family=31&lang=tr&mainModelCode=553210&servi...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41", "id" : "31" } }, { "name" : "COROLLA", "link" : { "`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr2
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr2?allMarkets=false&family=31&lang=tr&mainModelCode=553210&restr...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41", "id" : "31" } }, { "name" : "COROLLA", "link" : { "`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/restr3
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/restr3?allMarkets=false&family=31&lang=tr&mainModelCode=553210&restr...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41", "id" : "31" } }, { "name" : "COROLLA", "link" : { "`
- **Çağrı sayısı:** 1
### /p5toyota/extern/vehicle/modelCodes
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5toyota/extern/vehicle/modelCodes?allMarkets=false&family=31&lang=tr&mainModelCode=553210&r...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5toyota/extern/vehicle/modelFamilies?allMarkets=false&lang=tr&serviceName=toyota_parts&upds=2026-01-30--08-41", "id" : "31" } }, { "name" : "COROLLA", "link" : { "`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5toyota/extern/catmeta?serviceName=toyota_parts&cou...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Toyota", "user24Brand" : "Toyota", ` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?lang=tr&servic...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelFamilies?allMarkets=fal...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/models?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr1?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr2?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/restr3?allMarkets=false&fami...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
| GET | `https://www.partslink24.com/p5toyota/extern/vehicle/modelCodes?allMarkets=false&...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Toyota", "link" : { "wid" : "modelFamiliesTable", "` |
## Notlar
- Sayfa başlığı: Toyota, COROLLA, COROLLA CROSS (JPP) (Basl... - partslink24
- URL: https://www.partslink24.com/pl24-app/toyota_parts/0/eyJwYXRoIjoiL3A1dG95b3RhL2V4dGVybi92ZWhpY2xlL21vZGVsQ29kZXM%252FYWxsTWFya2V0cz1mYWxzZSZmYW1pbHk9MzEmbGFuZz10ciZtYWluTW9kZWxDb2RlPTU1MzIxMCZyZXN0cjE9X2FyYml0cmFyeV8mcmVzdHIyPV9hcmJpdHJhcnlfJnJlc3RyMz1fYXJiaXRyYXJ5XyZzZXJ2aWNlTmFtZT10b3lvdGFfcGFydHMmdXBkcz0yMDI2LTAxLTMwLS0wOC00MSIsIndpZCI6Im1vZGVsQ29kZXNUYWJsZSIsImF1dG8iOnRydWV9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Vauxhall — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:31:31.730Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Vauxhall - partslink24
- URL: https://www.partslink24.com/opel/vauxhall_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.21+07%3A11%3A24+CET
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Volkswagen Classic — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:32:02.771Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vwclassic_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Volkswagen Classic", "user24Brand" : "VW", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAAD9QTFRFR3BMADJeABdJP2uKADxm////ACNSAjxmfZqu+fv7Ll6AB0FpzNjfkKm68fX1HE9zvMvUpbnG3eXpVHuVaYyjLQdeSgAAAAp0Uk5TAP//////`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=vwclassic_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen Classic", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vwclassic_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=90059&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen Classic", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vwclassic_parts&upds=2026-02-13--00-01", "id" : "90059_11_null" } }, { "name" : "VW-I`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vwclassic_parts&co...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Volkswagen Classic", "user24Brand" : "V` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Classic", "link" : { "wid" : "modelFamiliesTab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Classic", "link" : { "wid" : "modelFamiliesTab` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=90059&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Classic", "link" : { "wid" : "modelFamiliesTab` |
## Notlar
- Sayfa başlığı: Volkswagen Classic - partslink24
- URL: https://www.partslink24.com/pl24-app/vwclassic_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT05MDA1OSZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9MTEmc2VydmljZU5hbWU9dndjbGFzc2ljX3BhcnRzJnVwZHM9MjAyNi0wMi0xMy0tMDAtMDEiLCJ3aWQiOiJtb2RlbFllYXJUYWJsZSJ9/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Volkswagen Commercial Vehicles — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:32:18.174Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vn_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Volkswagen Commercial Vehicles", "user24Brand" : "VW", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAAAXNSR0IArs4c6QAAACdQTFRFR3BMAB1RAB5QAB5QAB1QAB1QAB5QAB5QAB5QAB1QAB5QAB5QAB5QOuADRgAAAAx0Uk5TAA4gNk5lgJ23zuDx4n4xwwAADfdJ`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=vn_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen Commercial Vehicles", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vn_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records"`
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=90079&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen Commercial Vehicles", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vn_parts&upds=2026-02-13--00-01", "id" : "90079_3_12" } }, { "name" : "Ca`
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vn_parts&country=D...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Volkswagen Commercial Vehicles", "user2` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Commercial Vehicles", "link" : { "wid" : "mode` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Commercial Vehicles", "link" : { "wid" : "mode` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=90079&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen Commercial Vehicles", "link" : { "wid" : "mode` |
## Notlar
- Sayfa başlığı: Volkswagen Commercial Veh... - partslink24
- URL: https://www.partslink24.com/pl24-app/vn_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT05MDA3OSZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9MyZvcmRpbmFsTnVtYmVyMj0xMiZzZXJ2aWNlTmFtZT12bl9wYXJ0cyZ1cGRzPTIwMjYtMDItMTMtLTAwLTAxIiwid2lkIjoibW9kZWxZZWFyVGFibGUifQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,85 @@
# Volkswagen — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:31:47.327Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
### /pl24-appgtw/ext/api/1.0/legal/tr
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr`
- **Yanıt özeti:**
`{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-privacy/tr/tr/partslink24-privacy.html"},{"name":"partslink24-tos","url":"https://www.lexcom.de/legal/partslink24-tos/tr/tr/partslink24-tos.html"},{"name":"general-dataprocessing","url":"https://www.lexco`
- **Çağrı sayısı:** 1
### /p5vwag/extern/catmeta
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vw_parts&country=DE&lang=tr`
- **Yanıt özeti:**
`{ "data" : { "carbrand" : { "brandName" : "Volkswagen", "user24Brand" : "VW", "logo" : "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAAXNSR0IArs4c6QAAACRQTFRFR3BMADFeADBeADBfADBfADBfATBfATBfATBfATBfATBfATBf/cnSjQAAAAt0Uk5TAAsbMEpkgqK/2u8YmuyPAAAO5ElEQVR42uyYTU8TURSG73RKFVcT`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelfamilies
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceName=vw_parts`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vw_parts&upds=2026-02-13--00-01" } } ], "demo" : true, "data" : { "records" : [ { "id" : `
- **Çağrı sayısı:** 2
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", "btn_label_check_parts_for_vin": "Validate parts", "btn_label_create_cart": "Create shopping cart", "btn_label_create_new_cart": "Create new shopping cart", "btn_label_create_template": "Create `
- **Çağrı sayısı:** 1
### /pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.json`
- **Yanıt özeti:**
`{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_label_check_parts_for_vin": "Parçaları doğrula", "btn_label_create_cart": "Ürün sepeti oluştur", "btn_label_create_new_cart": "Yeni ürün sepeti oluştur", "btn_label_create_template": "Şablon oluştu`
- **Çağrı sayısı:** 1
### /p5vwag/extern/vehicle/modelyears
- **Method:** GET
- **Status:** 200
- **Faz:** marka-ana-sayfa
- **Örnek URL:**
`https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=84071&lang=tr&localMarketOnly=true&modelInfo=true...`
- **Yanıt özeti:**
`{ "crumbs" : [ { "name" : "Volkswagen", "link" : { "wid" : "modelFamiliesTable", "path" : "/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMarketOnly=true&serviceName=vw_parts&upds=2026-02-13--00-01", "id" : "84071_1_null" } }, { "name" : "ID.4", "link" : `
- **Çağrı sayısı:** 1
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| GET | `https://www.partslink24.com/pl24-appgtw/ext/api/1.0/legal/tr` | 200 | marka-ana-sayfa | `{"legalDocuments":[{"name":"partslink24-privacy","url":"https://www.lexcom.de/legal/partslink24-priv` |
| GET | `https://www.partslink24.com/p5vwag/extern/catmeta?serviceName=vw_parts&country=D...` | 200 | marka-ana-sayfa | `{ "data" : { "carbrand" : { "brandName" : "Volkswagen", "user24Brand" : "VW", ` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&serviceN...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen", "link" : { "wid" : "modelFamiliesTable", ` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelfamilies?lang=tr&localMar...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen", "link" : { "wid" : "modelFamiliesTable", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/en.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "To shopping cart selection", "back_to_template_list": "To templates", ` |
| GET | `https://www.partslink24.com/pl24-cart-embedded-ui/mf/2.0.14/assets/locales/tr.js...` | 200 | marka-ana-sayfa | `{ "back_to_cart_list": "ürün sepeti seçimine", "back_to_template_list": "şablonlara", "btn_lab` |
| GET | `https://www.partslink24.com/p5vwag/extern/vehicle/modelyears?familyKey=84071&lan...` | 200 | marka-ana-sayfa | `{ "crumbs" : [ { "name" : "Volkswagen", "link" : { "wid" : "modelFamiliesTable", ` |
## Notlar
- Sayfa başlığı: Volkswagen - partslink24
- URL: https://www.partslink24.com/pl24-app/vw_parts/0/eyJwYXRoIjoiL3A1dndhZy9leHRlcm4vdmVoaWNsZS9tb2RlbHllYXJzP2ZhbWlseUtleT04NDA3MSZsYW5nPXRyJmxvY2FsTWFya2V0T25seT10cnVlJm1vZGVsSW5mbz10cnVlJm9yZGluYWxOdW1iZXI9MSZzZXJ2aWNlTmFtZT12d19wYXJ0cyZ1cGRzPTIwMjYtMDItMTMtLTAwLTAxIiwid2lkIjoibW9kZWxZZWFyVGFibGUifQ%253D%253D/
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -0,0 +1,20 @@
# Volvo — PL24 Katalog Yapısı
## Keşif Tarihi
2026-02-24T13:32:33.632Z
## Tespit Edilen Endpoint'ler (Unique Path'ler)
_Hiç API isteği yakalanmadı._
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
| — | — | — | — | — |
## Notlar
- Sayfa başlığı: Volvo - partslink24
- URL: https://www.partslink24.com/volvo/volvo_parts/vehicle.action?mode=K00U0DEXX&lang=tr&startup=true&upds=2026.02.19+14%3A46%3A42
- İlk model tıklanamadı — selector bulunamadı

View File

@@ -3,11 +3,11 @@ module.exports = {
{ {
name: "sase-api", name: "sase-api",
cwd: "./apps/api", cwd: "./apps/api",
script: "pnpm", script: "node",
args: "dev", args: "--enable-source-maps dist/main.js",
exec_mode: "fork", exec_mode: "fork",
env: { env: {
NODE_ENV: "development", NODE_ENV: "production",
PORT: 4000, PORT: 4000,
OTEL_ENABLED: "true", OTEL_ENABLED: "true",
OTEL_SERVICE_NAME: "sase-api", OTEL_SERVICE_NAME: "sase-api",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -0,0 +1,122 @@
-- Migration: Shared Vehicle Config (car-config-centric architecture)
-- Converts per-user vehicle records to shared vehicle configs with junction table.
-- IMPORTANT: Take a DB backup before running. Execute inside a transaction.
BEGIN;
-- 1. Create user_vehicles junction table
CREATE TABLE user_vehicles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
vehicle_id UUID NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 2. For each VIN, pick the canonical record (most recently updated)
-- and migrate all userId-vehicleId pairs into the junction table
INSERT INTO user_vehicles (user_id, vehicle_id, created_at, last_accessed_at)
SELECT
v.user_id,
canonical.id,
v.created_at,
v.updated_at
FROM vehicles v
JOIN (
SELECT DISTINCT ON (vin) id, vin
FROM vehicles
ORDER BY vin, updated_at DESC NULLS LAST
) canonical ON canonical.vin = v.vin;
-- 3. Delete categories on NON-canonical vehicles that already exist on the
-- canonical vehicle (same name+source), so the UPDATE in step 4 won't
-- hit the unique constraint.
WITH canonical AS (
SELECT DISTINCT ON (vin) id AS cid, vin
FROM vehicles ORDER BY vin, updated_at DESC NULLS LAST
)
DELETE FROM categories
WHERE id IN (
SELECT c_dup.id
FROM categories c_dup
JOIN vehicles v ON c_dup.vehicle_id = v.id
JOIN canonical can ON can.vin = v.vin
WHERE v.id != can.cid
AND EXISTS (
SELECT 1 FROM categories c_can
WHERE c_can.vehicle_id = can.cid
AND c_can.name = c_dup.name
AND c_can.source = c_dup.source
)
);
-- 4. Move remaining categories from non-canonical vehicles to canonical
WITH canonical AS (
SELECT DISTINCT ON (vin) id AS cid, vin
FROM vehicles ORDER BY vin, updated_at DESC NULLS LAST
)
UPDATE categories c
SET vehicle_id = can.cid
FROM vehicles v JOIN canonical can ON can.vin = v.vin
WHERE c.vehicle_id = v.id AND v.id != can.cid;
-- 5. Delete parts on non-canonical vehicles that would conflict after move
-- (parts don't have a unique constraint, but let's keep data clean by
-- removing duplicates — same oemCode+categoryId on canonical vehicle)
WITH canonical AS (
SELECT DISTINCT ON (vin) id AS cid, vin
FROM vehicles ORDER BY vin, updated_at DESC NULLS LAST
)
DELETE FROM parts
WHERE id IN (
SELECT p_dup.id
FROM parts p_dup
JOIN vehicles v ON p_dup.vehicle_id = v.id
JOIN canonical can ON can.vin = v.vin
WHERE v.id != can.cid
AND EXISTS (
SELECT 1 FROM parts p_can
WHERE p_can.vehicle_id = can.cid
AND p_can.category_id = p_dup.category_id
AND p_can.oem_code = p_dup.oem_code
)
);
-- 6. Move remaining parts from non-canonical vehicles to canonical
WITH canonical AS (
SELECT DISTINCT ON (vin) id AS cid, vin
FROM vehicles ORDER BY vin, updated_at DESC NULLS LAST
)
UPDATE parts p
SET vehicle_id = can.cid
FROM vehicles v JOIN canonical can ON can.vin = v.vin
WHERE p.vehicle_id = v.id AND v.id != can.cid;
-- 7. Delete non-canonical vehicle records (duplicates)
DELETE FROM vehicles WHERE id NOT IN (
SELECT DISTINCT ON (vin) id FROM vehicles
ORDER BY vin, updated_at DESC NULLS LAST
);
-- 8. Drop old user-specific indexes and column
DROP INDEX IF EXISTS vehicles_user_vin_idx;
DROP INDEX IF EXISTS vehicles_user_id_idx;
ALTER TABLE vehicles DROP COLUMN user_id;
-- 9. Add unique index on VIN (one record per VIN globally)
CREATE UNIQUE INDEX vehicles_vin_unique_idx ON vehicles (vin);
-- 10. Add FK and indexes on junction table
ALTER TABLE user_vehicles
ADD CONSTRAINT user_vehicles_vehicle_id_fkey
FOREIGN KEY (vehicle_id) REFERENCES vehicles(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX user_vehicles_user_vehicle_idx ON user_vehicles (user_id, vehicle_id);
CREATE INDEX user_vehicles_user_id_idx ON user_vehicles (user_id);
-- 11. Drop unused vehicle_categories table
DROP TABLE IF EXISTS vehicle_categories;
-- Also drop the old vin-only index if it exists (replaced by unique)
DROP INDEX IF EXISTS vehicles_vin_idx;
COMMIT;

View File

@@ -0,0 +1,742 @@
#!/usr/bin/env node
/**
* PL24 Katalog Yapısı Keşif Script'i
*
* PL24 web arayüzüne (brandMenu.do) Playwright ile bağlanır,
* sol sidebar'daki her markayı tıklar ve arka planda yapılan
* XHR/fetch isteklerini intercept ederek API endpoint yapısını keşfeder.
* Her marka için docs/pl24-catalog/{brandSlug}.md oluşturur.
*
* Kullanım:
* node scripts/pl24-catalog-explorer.js # tüm markalar
* node scripts/pl24-catalog-explorer.js --brand VW # tek marka
* node scripts/pl24-catalog-explorer.js --headed # tarayıcı görünür
* node scripts/pl24-catalog-explorer.js --force # mevcut dosyaları yenile
* node scripts/pl24-catalog-explorer.js --delay 10000
*/
const { chromium } = require("playwright");
const fs = require("fs");
const path = require("path");
// PL24 .env'den kimlik bilgilerini yükle (dotenv bağımlılığı olmadan)
(function loadEnv() {
const envPath = path.join(__dirname, "../apps/api/.env");
if (!fs.existsSync(envPath)) return;
const lines = fs.readFileSync(envPath, "utf-8").split("\n");
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const eqIdx = trimmed.indexOf("=");
if (eqIdx < 1) continue;
const key = trimmed.substring(0, eqIdx).trim();
const val = trimmed.substring(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
if (!process.env[key]) process.env[key] = val;
}
})();
// ── Config ──────────────────────────────────────────────────────────────────
const CONFIG = {
pl24BaseUrl: process.env.PL24_BASE_URL || "https://www.partslink24.com",
companyCode: process.env.PL24_COMPANY_CODE || "",
username: process.env.PL24_USERNAME || "",
password: process.env.PL24_PASSWORD || "",
brandMenuUrl: "/partslink24/user/brandMenu.do",
headless: true,
delayBetweenBrands: 8000, // ms — rate limit koruması
delayBetweenClicks: 3000, // ms — marka içi tıklamalar arası
navigationTimeout: 60000,
actionTimeout: 30000,
networkIdleTimeout: 5000, // API isteklerinin gelmesi için bekleme
outputDir: path.join(__dirname, "../docs/pl24-catalog"),
force: false,
filterBrand: null,
};
// ── CLI Args ─────────────────────────────────────────────────────────────────
function parseArgs() {
const args = process.argv.slice(2);
const opts = { ...CONFIG };
for (let i = 0; i < args.length; i++) {
if (args[i] === "--headed") opts.headless = false;
if (args[i] === "--headless") opts.headless = true;
if (args[i] === "--force") opts.force = true;
if (args[i] === "--brand" && args[i + 1]) opts.filterBrand = args[++i].toUpperCase();
if (args[i] === "--delay" && args[i + 1]) opts.delayBetweenBrands = parseInt(args[++i], 10);
}
return opts;
}
// ── Helpers ──────────────────────────────────────────────────────────────────
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function ts() {
return new Date().toISOString().replace("T", " ").substring(0, 19);
}
function log(msg) {
console.log(`[${ts()}] ${msg}`);
}
function logSection(title) {
console.log(`\n${"═".repeat(70)}\n ${title}\n${"═".repeat(70)}`);
}
function slugify(name) {
return name
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "");
}
function isApiRequest(url) {
// Sadece JSON API isteklerini filtrele
const u = url.toLowerCase();
return (
u.includes("/extern/") ||
u.includes("/p5vwag/") ||
u.includes("/p5bmw/") ||
u.includes("/p5daimler/") ||
u.includes("/p5toyota/") ||
u.includes("/p5jlr/") ||
u.includes("/p5renault/") ||
u.includes("/p5stellantis/") ||
u.includes("/p5hyundai/") ||
u.includes("/p5nissan/") ||
u.includes("/p5volvo/") ||
u.includes("/p5opel/") ||
u.includes("/ford/") ||
u.includes("/pl24-appgtw/") ||
u.includes("/pl24-manufacturer/") ||
u.includes("/auth/ext/") ||
(u.includes("partslink24.com") && (u.includes(".json") || u.includes("/api/")))
);
}
// ── Keşif Notları Yardımcısı ─────────────────────────────────────────────────
class BrandExplorer {
constructor(brandName) {
this.brandName = brandName;
this.requests = [];
this.notes = [];
this.startedAt = new Date().toISOString();
}
addRequest({ method, url, status, responseBody, phase }) {
this.requests.push({ method, url, status, responseBody, phase });
}
addNote(note) {
this.notes.push(note);
log(` NOTE: ${note}`);
}
generateMd() {
// Unique URL'leri grupla
const byPath = {};
for (const r of this.requests) {
try {
const u = new URL(r.url);
const pathKey = u.pathname;
if (!byPath[pathKey]) byPath[pathKey] = { ...r, count: 0, params: [] };
byPath[pathKey].count++;
if (u.search) byPath[pathKey].params.push(u.search);
} catch {
// geçersiz URL
}
}
const endpointList = Object.entries(byPath)
.map(([p, r]) => {
const exampleUrl = r.url.length > 120 ? r.url.substring(0, 120) + "..." : r.url;
const bodyPreview = r.responseBody
? r.responseBody.substring(0, 300).replace(/\n/g, " ")
: "(yanıt yok)";
return `### ${p}\n- **Method:** ${r.method}\n- **Status:** ${r.status || "?"}\n- **Faz:** ${r.phase}\n- **Örnek URL:**\n \`${exampleUrl}\`\n- **Yanıt özeti:**\n \`${bodyPreview}\`\n- **Çağrı sayısı:** ${r.count}\n`;
})
.join("\n");
const requestTable = this.requests
.map((r) => {
const shortUrl = r.url.length > 80 ? r.url.substring(0, 80) + "..." : r.url;
const body = r.responseBody
? r.responseBody.substring(0, 100).replace(/\|/g, "\\|").replace(/\n/g, " ")
: "";
return `| ${r.method} | \`${shortUrl}\` | ${r.status || "?"} | ${r.phase} | \`${body}\` |`;
})
.join("\n");
const notesList = this.notes.map((n) => `- ${n}`).join("\n") || "- Özel not yok";
return `# ${this.brandName} — PL24 Katalog Yapısı
## Keşif Tarihi
${this.startedAt}
## Tespit Edilen Endpoint'ler (Unique Path'ler)
${endpointList || "_Hiç API isteği yakalanmadı._"}
## Ham Yakalanan İstekler
| Method | URL | Status | Faz | Response (ilk 100 char) |
|--------|-----|--------|-----|------------------------|
${requestTable || "| — | — | — | — | — |"}
## Notlar
${notesList}
`;
}
}
// ── Login ────────────────────────────────────────────────────────────────────
/**
* PL24 REST API üzerinden login olup session cookie'yi Playwright context'e enjekte eder.
* Web formu yerine doğrudan /pl24-appgtw/ext/api/1.0/login endpoint'i kullanılır.
*/
async function loginToPL24(page, opts) {
log("PL24 REST API login başlıyor...");
// 1. REST API ile login — web form bypass
const loginBody = {
authentication: {
account: opts.companyCode,
user: opts.username,
pwd: opts.password,
},
device: {
id: "0",
os: "Windows 10",
offset: "0",
lang: "en-US",
"os-version": "0",
},
"app-version": "",
squeezeOut: true,
};
const loginResp = await fetch(
`${opts.pl24BaseUrl}/pl24-appgtw/ext/api/1.0/login`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
},
body: JSON.stringify(loginBody),
signal: AbortSignal.timeout(opts.actionTimeout),
},
);
if (!loginResp.ok) {
throw new Error(`REST login HTTP ${loginResp.status}`);
}
const loginData = await loginResp.json();
if (!loginData.token?.access_token) {
throw new Error(`REST login başarısız: ${loginData.status}${loginData.message || "token yok"}`);
}
const accessToken = loginData.token.access_token;
log(`REST login başarılı. Token: ${accessToken.substring(0, 30)}...`);
// Session cookie
const setCookie = loginResp.headers.get("set-cookie") || "";
const pl24TokenMatch = setCookie.match(/PL24TOKEN=([^;]+)/);
const jsessionMatch = setCookie.match(/JSESSIONID=([^;]+)/);
const pl24Token = pl24TokenMatch ? `PL24TOKEN=${pl24TokenMatch[1]}` : "";
const jsession = jsessionMatch ? `JSESSIONID=${jsessionMatch[1]}` : "";
log(`Cookie: ${pl24Token || jsession || "(yok)"}`);
// 2. Cookie'leri Playwright context'e enjekte et
const context = page.context();
const cookiesToSet = [];
if (pl24TokenMatch) {
cookiesToSet.push({ name: "PL24TOKEN", value: pl24TokenMatch[1], domain: "www.partslink24.com", path: "/" });
}
if (jsessionMatch) {
cookiesToSet.push({ name: "JSESSIONID", value: jsessionMatch[1], domain: "www.partslink24.com", path: "/" });
}
if (cookiesToSet.length > 0) {
await context.addCookies(cookiesToSet);
log(`${cookiesToSet.length} cookie enjekte edildi`);
}
// 3. Önce ana sayfayı ziyaret et (session kurmak için)
log("Ana sayfa ziyaret ediliyor...");
await page.goto(`${opts.pl24BaseUrl}/`, {
waitUntil: "networkidle",
timeout: opts.navigationTimeout,
});
// 4. Formu JWT token ile doldurarak login yap
const currentUrl = page.url();
log(`URL: ${currentUrl}`);
if (currentUrl.includes("brandMenu")) {
log("Giriş yapılmış (cookie çalıştı)");
return;
}
if (currentUrl.includes("login")) {
// Form görünüyor — doldur ve submit et
log("Login formu dolduruluyor...");
await page.fill("#login-id", opts.companyCode);
await page.fill("#login-name", opts.username);
await page.fill("#inputPassword", opts.password);
// JavaScript ile doLoginAjax çağır
log("doLoginAjax çağrılıyor...");
await page.evaluate(() => {
if (typeof doLoginAjax === "function") {
doLoginAjax(false);
}
});
// Redirect bekle
try {
await page.waitForURL(/brandMenu|portal|welcome/, { timeout: 30000 });
log("Login başarılı — redirect oldu");
} catch {
await sleep(3000);
const url2 = page.url();
log(`Login sonrası URL: ${url2}`);
if (url2.includes("login")) {
// HTML hata mesajını kaydet
const html = await page.content();
require("fs").writeFileSync("/tmp/pl24-login-error.html", html);
throw new Error(`Login başarısız: ${url2} (HTML → /tmp/pl24-login-error.html)`);
}
}
}
// 5. brandMenu.do'ya git
log("brandMenu.do'ya gidiliyor...");
await page.goto(`${opts.pl24BaseUrl}/partslink24/user/brandMenu.do`, {
waitUntil: "networkidle",
timeout: opts.navigationTimeout,
});
const finalUrl = page.url();
log(`brandMenu URL: ${finalUrl}`);
if (finalUrl.includes("login")) {
throw new Error(`brandMenu'ya erişilemedi, login gerekiyor: ${finalUrl}`);
}
log("PL24'e başarıyla giriş yapıldı!");
}
// ── Marka Listesi ─────────────────────────────────────────────────────────────
async function getBrandList(page) {
log("Marka listesi okunuyor...");
// brandMenu.do'da markalar: <a class="brand-logo" href="/partslink24/launchCatalog.do?service=vw_parts&t=..." title="Volkswagen">
try {
const count = await page.locator("a.brand-logo").count();
if (count > 0) {
log(` a.brand-logo selector: ${count} marka bulundu`);
const brands = await page.$$eval("a.brand-logo", (els) =>
els.map((el) => {
const href = el.getAttribute("href") || "";
// service adını URL'den çıkar: ?service=vw_parts&...
const serviceMatch = href.match(/[?&]service=([^&]+)/);
return {
name: el.getAttribute("title") || el.textContent?.trim() || "",
href,
service: serviceMatch ? serviceMatch[1] : "",
onclick: el.getAttribute("onclick") || "",
};
}).filter((b) => b.name.length > 0)
);
// Servis adına göre deduplicate (brandMenu.do her markayı 2 kez gösteriyor)
const seen = new Set();
const unique = brands.filter((b) => {
if (!b.service || seen.has(b.service)) return false;
seen.add(b.service);
return true;
});
log(` ${unique.length} marka listelendi (${brands.length - unique.length} duplicate atlandı):`);
for (const b of unique) {
log(` ${b.name} (${b.service}) → ${b.href.substring(0, 60)}`);
}
return unique;
}
} catch (err) {
log(` a.brand-logo selector hatası: ${err.message}`);
}
// Fallback: launchCatalog.do içeren linkleri ara
log(" Fallback: launchCatalog.do linkleri aranıyor...");
try {
const brands = await page.$$eval("a[href*='launchCatalog']", (els) =>
els.map((el) => {
const href = el.getAttribute("href") || "";
const serviceMatch = href.match(/[?&]service=([^&]+)/);
const title = el.getAttribute("title") || el.textContent?.trim() || "";
return {
name: title,
href,
service: serviceMatch ? serviceMatch[1] : "",
onclick: el.getAttribute("onclick") || "",
};
}).filter((b) => b.name.length > 0)
);
if (brands.length > 0) {
log(` ${brands.length} marka (launchCatalog fallback):`);
for (const b of brands) {
log(` ${b.name} (${b.service})`);
}
return brands;
}
} catch { /* devam */ }
// Son çare: sayfa kaynağını kaydet ve hata ver
log(" UYARI: Marka listesi bulunamadı, sayfa HTML kaydediliyor...");
const bodyHtml = await page.evaluate(() => document.body?.innerHTML?.substring(0, 5000) || "");
log(" Sayfa HTML (ilk 5000 char):");
console.log(bodyHtml);
return [];
}
// ── Tek Marka Keşfi ───────────────────────────────────────────────────────────
async function exploreBrand(page, brand, opts) {
const explorer = new BrandExplorer(brand.name);
log(`\nKeşif başlıyor: ${brand.name}`);
// Network intercept'i başlat
const requestLog = [];
const onRequest = (req) => {
const url = req.url();
if (isApiRequest(url)) {
requestLog.push({ method: req.method(), url, phase: "request", status: null, responseBody: null });
}
};
const onResponse = async (res) => {
const url = res.url();
if (!isApiRequest(url)) return;
const status = res.status();
let responseBody = null;
try {
const ct = res.headers()["content-type"] || "";
if (ct.includes("json") || ct.includes("text")) {
const text = await res.text();
responseBody = text.substring(0, 1000);
}
} catch { /* body alınamadı */ }
// Mevcut request'i güncelle veya yeni ekle
const existing = requestLog.find((r) => r.url === url && r.status === null);
if (existing) {
existing.status = status;
existing.responseBody = responseBody;
} else {
requestLog.push({ method: res.request().method(), url, phase: "response", status, responseBody });
}
};
page.on("request", onRequest);
page.on("response", onResponse);
try {
// ── Faz 1: Markayı tıkla ──────────────────────────────────────────────
log(` Faz 1: Marka tıklanıyor — ${brand.name}`);
if (brand.href && brand.href !== "#" && brand.href !== "") {
const fullUrl = brand.href.startsWith("http")
? brand.href
: `${opts.pl24BaseUrl}${brand.href}`;
await page.goto(fullUrl, { waitUntil: "domcontentloaded", timeout: opts.navigationTimeout });
} else if (brand.onclick) {
await page.evaluate((onclick) => eval(onclick), brand.onclick);
} else {
// Metin ile bul ve tıkla
const el = page.locator(`a:has-text("${brand.name}")`).first();
await el.click();
}
// API isteklerinin gelmesi için bekle
await sleep(opts.networkIdleTimeout);
// Sayfanın yapısını incele
const pageTitle = await page.title().catch(() => "");
log(` Sayfa başlığı: ${pageTitle}`);
explorer.addNote(`Sayfa başlığı: ${pageTitle}`);
explorer.addNote(`URL: ${page.url()}`);
// Faz 1 isteklerini kaydet
const phase1Requests = [...requestLog];
for (const r of phase1Requests) {
explorer.addRequest({ ...r, phase: "marka-ana-sayfa" });
}
requestLog.length = 0;
log(` Faz 1: ${phase1Requests.length} API isteği yakalandı`);
// ── Faz 2: İlk model/araç'ı tıkla ──────────────────────────────────────
log(" Faz 2: İlk model aranıyor...");
const modelSelectors = [
".model-list li:first-child a",
".vehicleList li:first-child a",
".modelSeries li:first-child a",
"table.models tr:nth-child(2) td:first-child a",
".content a:first-child",
"ul li a:first-child",
];
let modelClicked = false;
for (const sel of modelSelectors) {
try {
const el = page.locator(sel).first();
if (await el.isVisible({ timeout: 2000 })) {
const modelName = await el.textContent();
log(` İlk model tıklanıyor: "${modelName?.trim()}" (${sel})`);
await el.click();
await sleep(opts.delayBetweenClicks);
modelClicked = true;
explorer.addNote(`İlk model tıklandı: "${modelName?.trim()}"`);
break;
}
} catch { /* devam */ }
}
if (!modelClicked) {
explorer.addNote("İlk model tıklanamadı — selector bulunamadı");
log(" Faz 2: Model selector bulunamadı, atlanıyor");
}
// Faz 2 isteklerini kaydet
const phase2Requests = [...requestLog];
for (const r of phase2Requests) {
explorer.addRequest({ ...r, phase: "model-secim" });
}
requestLog.length = 0;
log(` Faz 2: ${phase2Requests.length} ek API isteği yakalandı`);
// ── Faz 3: Kategoriler ───────────────────────────────────────────────────
log(" Faz 3: Kategori yapısı inceleniyor...");
const categorySelectors = [
".mainGroup li:first-child a",
".categoryList li:first-child a",
".groups li:first-child a",
"ul.mainGroups li:first-child a",
];
for (const sel of categorySelectors) {
try {
const el = page.locator(sel).first();
if (await el.isVisible({ timeout: 2000 })) {
const catName = await el.textContent();
log(` İlk kategori tıklanıyor: "${catName?.trim()}" (${sel})`);
await el.click();
await sleep(opts.delayBetweenClicks);
explorer.addNote(`İlk kategori tıklandı: "${catName?.trim()}"`);
break;
}
} catch { /* devam */ }
}
const phase3Requests = [...requestLog];
for (const r of phase3Requests) {
explorer.addRequest({ ...r, phase: "kategori" });
}
requestLog.length = 0;
log(` Faz 3: ${phase3Requests.length} ek API isteği yakalandı`);
} catch (err) {
explorer.addNote(`HATA: ${err.message}`);
log(` HATA: ${err.message}`);
} finally {
page.off("request", onRequest);
page.off("response", onResponse);
}
return explorer;
}
// ── Ana Akış ─────────────────────────────────────────────────────────────────
async function main() {
const opts = parseArgs();
if (!opts.companyCode || !opts.username || !opts.password) {
console.error("HATA: PL24 kimlik bilgileri eksik. apps/api/.env dosyasını kontrol edin.");
process.exit(1);
}
// Çıktı dizinini oluştur
if (!fs.existsSync(opts.outputDir)) {
fs.mkdirSync(opts.outputDir, { recursive: true });
}
logSection("PL24 KATALOG KEŞİF ARACI");
log(`PL24 URL: ${opts.pl24BaseUrl}`);
log(`Headless: ${opts.headless}, Delay: ${opts.delayBetweenBrands}ms, Force: ${opts.force}`);
if (opts.filterBrand) log(`Marka filtresi: ${opts.filterBrand}`);
// Tarayıcı başlat
const browser = await chromium.launch({
headless: opts.headless,
args: ["--no-sandbox", "--disable-setuid-sandbox"],
});
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
ignoreHTTPSErrors: true,
userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
});
context.setDefaultTimeout(opts.actionTimeout);
context.setDefaultNavigationTimeout(opts.navigationTimeout);
const page = await context.newPage();
try {
// Login
logSection("LOGIN");
await loginToPL24(page, opts);
// Screenshot: brandMenu
await page.screenshot({
path: path.join(opts.outputDir, "_brandmenu-screenshot.png"),
});
log("brandMenu.do ekran görüntüsü kaydedildi");
// Marka listesi
logSection("MARKA LİSTESİ");
let brands = await getBrandList(page);
if (brands.length === 0) {
log("UYARI: Marka listesi boş — sayfa yapısı analiz ediliyor...");
// Sayfa kaynağını kaydet
const html = await page.content();
fs.writeFileSync(path.join(opts.outputDir, "_brandmenu-source.html"), html);
log("Sayfa kaynağı _brandmenu-source.html olarak kaydedildi");
}
log(`Toplam ${brands.length} marka bulundu`);
// Filtrele (hem marka adına hem service adına bak)
if (opts.filterBrand) {
brands = brands.filter((b) =>
b.name.toUpperCase().includes(opts.filterBrand) ||
(b.service || "").toUpperCase().includes(opts.filterBrand)
);
log(`Filtre sonrası: ${brands.length} marka`);
}
if (brands.length === 0) {
log("İşlenecek marka yok. Çıkılıyor.");
return;
}
// Özet için marka bilgilerini tut
const summaryData = [];
// ── Her Marka ─────────────────────────────────────────────────────────
for (let i = 0; i < brands.length; i++) {
const brand = brands[i];
const slug = slugify(brand.name);
const outFile = path.join(opts.outputDir, `${slug}.md`);
logSection(`[${i + 1}/${brands.length}] ${brand.name}`);
// Resume: zaten keşfedildiyse atla
if (!opts.force && fs.existsSync(outFile)) {
log(`Atlanıyor (zaten mevcut): ${outFile}`);
summaryData.push({ name: brand.name, slug, status: "atlandı (mevcut)" });
continue;
}
// brandMenu.do'ya dön (her marka keşfinden önce)
if (i > 0) {
try {
await page.goto(`${opts.pl24BaseUrl}${opts.brandMenuUrl}`, {
waitUntil: "domcontentloaded",
timeout: opts.navigationTimeout,
});
await sleep(2000);
} catch (err) {
log(`brandMenu.do'ya dönülemedi: ${err.message}`);
}
}
// Keşfet
const explorer = await exploreBrand(page, brand, opts);
const md = explorer.generateMd();
// Kaydet
fs.writeFileSync(outFile, md, "utf-8");
log(`Kaydedildi: ${outFile}`);
summaryData.push({
name: brand.name,
slug,
status: "tamamlandı",
requestCount: explorer.requests.length,
});
// Rate limit
if (i < brands.length - 1) {
log(`Bekleniyor: ${opts.delayBetweenBrands}ms...`);
await sleep(opts.delayBetweenBrands);
}
}
// ── Özet Dosyası ──────────────────────────────────────────────────────
logSection("ÖZET");
const summaryLines = summaryData.map((s) =>
`| ${s.name} | ${s.slug} | ${s.status} | ${s.requestCount ?? "-"} |`
).join("\n");
const summaryMd = `# PL24 Katalog Keşif Özeti
## Keşif Tarihi
${new Date().toISOString()}
## Sonuçlar
| Marka | Slug | Durum | API İstek Sayısı |
|-------|------|-------|-----------------|
${summaryLines}
## Notlar
- Bu dosya otomatik olarak oluşturulmuştur
- Her marka için ayrıntı: \`{slug}.md\`
`;
fs.writeFileSync(path.join(opts.outputDir, "_summary.md"), summaryMd, "utf-8");
log(`Özet kaydedildi: ${path.join(opts.outputDir, "_summary.md")}`);
log(`\nKeşif tamamlandı. ${summaryData.length} marka işlendi.`);
log(`Çıktı dizini: ${opts.outputDir}`);
} finally {
await browser.close();
}
}
main().catch((err) => {
console.error(`FATAL: ${err.message}`);
console.error(err.stack);
process.exit(1);
});

280
scripts/posthog-dashboards.sh Executable file
View File

@@ -0,0 +1,280 @@
#!/usr/bin/env bash
set -euo pipefail
API_KEY="${POSTHOG_API_KEY:?Set POSTHOG_API_KEY env var}"
BASE="https://eu.posthog.com/api/projects/127747"
HEADERS=(-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json")
create_insight() {
local payload="$1"
local response
response=$(curl -s -X POST "$BASE/insights/" "${HEADERS[@]}" -d "$payload")
local id
id=$(echo "$response" | jq -r '.id')
if [[ "$id" == "null" || -z "$id" ]]; then
echo "ERROR creating insight: $response" >&2
exit 1
fi
echo "$id"
}
add_to_dashboard() {
local insight_id="$1"
local dashboard_id="$2"
curl -s -X PATCH "$BASE/insights/$insight_id/" "${HEADERS[@]}" \
-d "{\"dashboards\":[$dashboard_id]}" | jq -r '.id' > /dev/null
}
create_dashboard() {
local name="$1"
local response
response=$(curl -s -X POST "$BASE/dashboards/" "${HEADERS[@]}" \
-d "{\"name\":\"$name\"}")
local id
id=$(echo "$response" | jq -r '.id')
if [[ "$id" == "null" || -z "$id" ]]; then
echo "ERROR creating dashboard: $response" >&2
exit 1
fi
echo "$id"
}
echo "=== PostHog Dashboard Oluşturucu ==="
echo ""
# ─── Insight'lar ─────────────────────────────────────────────────────
echo "--- Insight'lar oluşturuluyor ---"
I1=$(create_insight '{
"name": "Günlük Aktif Kullanıcılar",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [{"kind":"EventsNode","event":"$pageview","math":"dau","name":"DAU"}],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [1/11] Günlük Aktif Kullanıcılar → $I1"
I2=$(create_insight '{
"name": "Kayıt Trendi",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [{"kind":"EventsNode","event":"user_signed_up","math":"total","name":"Kayıt"}],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [2/11] Kayıt Trendi → $I2"
I3=$(create_insight '{
"name": "Giriş / Çıkış",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [
{"kind":"EventsNode","event":"user_logged_in","math":"total","name":"Giriş"},
{"kind":"EventsNode","event":"user_logged_out","math":"total","name":"Çıkış"}
],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [3/11] Giriş / Çıkış → $I3"
I4=$(create_insight '{
"name": "VIN Arama Hacmi",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [
{"kind":"EventsNode","event":"vin_decoded","math":"total","name":"Arama"},
{"kind":"EventsNode","event":"vin_decode_success","math":"total","name":"Başarılı"},
{"kind":"EventsNode","event":"vin_decode_error","math":"total","name":"Hata"}
],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [4/11] VIN Arama Hacmi → $I4"
I5=$(create_insight '{
"name": "Onboarding Funnel",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "FunnelsQuery",
"series": [
{"kind":"EventsNode","event":"user_signed_up","name":"Kayıt"},
{"kind":"EventsNode","event":"trial_started","name":"Trial"},
{"kind":"EventsNode","event":"vin_decoded","name":"VIN Arama"},
{"kind":"EventsNode","event":"vin_decode_success","name":"Başarılı Sonuç"}
],
"dateRange": {"date_from": "-30d"},
"funnelsFilter": {"funnelWindowInterval": 14, "funnelWindowIntervalUnit": "day"}
}
}
}')
echo " [5/11] Onboarding Funnel → $I5"
I6=$(create_insight '{
"name": "Monetization Funnel",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "FunnelsQuery",
"series": [
{"kind":"EventsNode","event":"vin_decoded","name":"VIN Arama"},
{"kind":"EventsNode","event":"plan_selected","name":"Plan Seçimi"},
{"kind":"EventsNode","event":"checkout_started","name":"Checkout"},
{"kind":"EventsNode","event":"payment_initiated","name":"Ödeme"}
],
"dateRange": {"date_from": "-30d"},
"funnelsFilter": {"funnelWindowInterval": 14, "funnelWindowIntervalUnit": "day"}
}
}
}')
echo " [6/11] Monetization Funnel → $I6"
I7=$(create_insight '{
"name": "Core Value Funnel",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "FunnelsQuery",
"series": [
{"kind":"EventsNode","event":"user_logged_in","name":"Giriş"},
{"kind":"EventsNode","event":"vin_decoded","name":"VIN Arama"},
{"kind":"EventsNode","event":"vin_decode_success","name":"Başarılı Sonuç"}
],
"dateRange": {"date_from": "-30d"},
"funnelsFilter": {"funnelWindowInterval": 7, "funnelWindowIntervalUnit": "day"}
}
}
}')
echo " [7/11] Core Value Funnel → $I7"
I8=$(create_insight '{
"name": "Ödeme Trendi",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [
{"kind":"EventsNode","event":"payment_initiated","math":"total","name":"Ödeme Başlatıldı"},
{"kind":"EventsNode","event":"receipt_uploaded","math":"total","name":"Dekont Yüklendi"}
],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [8/11] Ödeme Trendi → $I8"
I9=$(create_insight '{
"name": "Trial Başlatma Trendi",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [{"kind":"EventsNode","event":"trial_started","math":"total","name":"Trial"}],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [9/11] Trial Başlatma Trendi → $I9"
I10=$(create_insight '{
"name": "İptal / Devam",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "TrendsQuery",
"series": [
{"kind":"EventsNode","event":"subscription_cancelled","math":"total","name":"İptal"},
{"kind":"EventsNode","event":"subscription_resumed","math":"total","name":"Devam"}
],
"dateRange": {"date_from": "-30d"},
"interval": "day"
}
}
}')
echo " [10/11] İptal / Devam → $I10"
I11=$(create_insight '{
"name": "Ödeme Funnel",
"query": {
"kind": "InsightVizNode",
"source": {
"kind": "FunnelsQuery",
"series": [
{"kind":"EventsNode","event":"plan_selected","name":"Plan Seçimi"},
{"kind":"EventsNode","event":"checkout_started","name":"Checkout"},
{"kind":"EventsNode","event":"payment_initiated","name":"Ödeme"},
{"kind":"EventsNode","event":"receipt_uploaded","name":"Dekont"}
],
"dateRange": {"date_from": "-30d"},
"funnelsFilter": {"funnelWindowInterval": 7, "funnelWindowIntervalUnit": "day"}
}
}
}')
echo " [11/11] Ödeme Funnel → $I11"
# ─── Dashboard'lar ───────────────────────────────────────────────────
echo ""
echo "--- Dashboard'lar oluşturuluyor ---"
D1=$(create_dashboard "SASE — Genel Bakış")
echo " Dashboard 1: SASE — Genel Bakış → $D1"
D2=$(create_dashboard "SASE — Funnel'lar")
echo " Dashboard 2: SASE — Funnel'lar → $D2"
D3=$(create_dashboard "SASE — Abonelik")
echo " Dashboard 3: SASE — Abonelik → $D3"
# ─── Insight → Dashboard bağlantıları ────────────────────────────────
echo ""
echo "--- Insight'lar dashboard'lara bağlanıyor ---"
# Dashboard 1: Genel Bakış
for id in "$I1" "$I2" "$I3" "$I4"; do
add_to_dashboard "$id" "$D1"
done
echo " Genel Bakış: 4 insight bağlandı"
# Dashboard 2: Funnel'lar
for id in "$I5" "$I6" "$I7" "$I8"; do
add_to_dashboard "$id" "$D2"
done
echo " Funnel'lar: 4 insight bağlandı"
# Dashboard 3: Abonelik
for id in "$I9" "$I10" "$I11"; do
add_to_dashboard "$id" "$D3"
done
echo " Abonelik: 3 insight bağlandı"
echo ""
echo "=== Tamamlandı ==="
echo ""
echo "Dashboard URL'leri:"
echo " https://eu.posthog.com/project/127747/dashboard/$D1 (Genel Bakış)"
echo " https://eu.posthog.com/project/127747/dashboard/$D2 (Funnel'lar)"
echo " https://eu.posthog.com/project/127747/dashboard/$D3 (Abonelik)"
echo ""
echo "Toplam: 11 insight + 3 dashboard oluşturuldu."

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 KiB

After

Width:  |  Height:  |  Size: 584 KiB

10
skills-lock.json Normal file
View File

@@ -0,0 +1,10 @@
{
"version": 1,
"skills": {
"seo-audit": {
"source": "coreyhaines31/marketingskills",
"sourceType": "github",
"computedHash": "6bd4cde58bb701b5dc90a0fae2f0ea3efc7c3e6fd2ae754083fa659930e7d39f"
}
}
}