// Filtreleme sorgusu
ShopProduct::where('category_id', 7) // Yedek Parça kategorisi
->orWhereHas('category', fn($q) => $q->where('parent_id', 7))
->where(function($q) {
$q->whereNull('parent_id')
->orWhere('parent_id', 0);
})
->get();
// Açıklama:
// - category_id = 7: Direkt yedek parça kategorisinde
// - parent category = 7: Alt kategoride ama yedek parçaya ait
// - parent_id IS NULL: Ana ürün (variant değil)
$hasContent = !empty($product->body['tr']) && strlen($product->body['tr']) > 100;
if ($hasContent) {
// BRANCH A: Mevcut içerik VAR
} else {
// BRANCH B: Mevcut içerik YOK
}
"IMPROVE and EXPAND this existing content:
{$existingBody}
EXISTING SPECS:
{$extractedSpecs}
RULES:
✅ KEEP all technical details
✅ EXPAND descriptions
✅ ADD SEO keywords
✅ Pattern v4 HTML
❌ NO price information
Bilingual: TR + EN"
"Generate GENERAL product content:
Title: {$title}
Category: Forklift Yedek Parça
RULES:
✅ General description ONLY
❌ NO specific dimensions/weight/voltage
❌ NO price information
✅ Use phrases: 'contact for details'
✅ SEO keywords
✅ Pattern v4 HTML
Bilingual: TR + EN"
Dosya: Modules/Shop/app/Services/ProductFilterService.php
Sorumluluk: Sadece yedek parça + variant olmayan ürünleri filtrele
class ProductFilterService
{
public function getEligibleProducts(): Collection
{
return ShopProduct::where('category_id', 7)
->orWhereHas('category', fn($q) => $q->where('parent_id', 7))
->where(function($q) {
$q->whereNull('parent_id')
->orWhere('parent_id', 0);
})
->get();
}
public function isEligible(ShopProduct $product): bool
{
// Yedek parça kategorisi mi?
if ($product->category_id != 7 &&
$product->category->parent_id != 7) {
return false;
}
// Variant ürün mü?
if ($product->parent_id && $product->parent_id > 0) {
return false;
}
return true;
}
}
Dosya: Modules/Shop/app/Services/ContentStrategyRouter.php
Sorumluluk: Mevcut içerik kontrolü → Branch A veya B
class ContentStrategyRouter
{
public function route(ShopProduct $product): string
{
$hasContent = !empty($product->body['tr']) &&
strlen($product->body['tr']) > 100;
return $hasContent ? 'expand' : 'create';
}
public function extractExistingData(ShopProduct $product): array
{
// Mevcut içerikten teknik detayları çıkar
$body = $product->body['tr'] ?? '';
return [
'specs' => $this->extractSpecs($body),
'existing_body' => $body,
'primary_specs' => $product->primary_specs,
'faq_data' => $product->faq_data,
];
}
protected function extractSpecs(string $body): array
{
// Regex ile boyut, ağırlık, voltaj vb. çıkar
// "150mm", "2.5 kg", "220V" gibi
}
}
Dosya: Modules/Shop/app/Services/ShopProductAIContentService.php
Sorumluluk: Strategy'ye göre farklı prompt
class ShopProductAIContentService
{
public function generate(ShopProduct $product): array
{
$strategy = $this->router->route($product);
if ($strategy === 'expand') {
return $this->expandExistingContent($product);
} else {
return $this->createNewContent($product);
}
}
protected function expandExistingContent($product): array
{
$existing = $this->router->extractExistingData($product);
$prompt = "IMPROVE this content:
{$existing['existing_body']}
KEEP: {$existing['specs']}
ADD: SEO keywords
NO PRICE!";
return $this->callGPT4($prompt);
}
protected function createNewContent($product): array
{
$prompt = "CREATE general content:
Title: {$product->title}
Category: Yedek Parça
NO SPECS! NO PRICE!
General description only.";
return $this->callGPT4($prompt);
}
}
Dosya: Modules/Shop/app/Services/ContentValidator.php
public function validate($content, $strategy): array
{
$errors = [];
// Fiyat kontrolü (HER ZAMAN)
if ($this->containsPrice($content)) {
$errors[] = 'Content contains price';
}
// Teknik detay kontrolü (SADECE Branch B)
if ($strategy === 'create' &&
$this->containsTechnicalSpecs($content)) {
$errors[] = 'New content should not have specs';
}
return $errors;
}
UI Değişiklikleri:
Görsel stratejisi değişmedi - context görseller üretecek
-- Direkt yedek parça kategorisinde
SELECT * FROM shop_products
WHERE category_id = 7
AND (parent_id IS NULL OR parent_id = 0);
-- Alt kategori ama yedek parçaya ait
SELECT p.*
FROM shop_products p
JOIN shop_categories c ON p.category_id = c.id
WHERE c.parent_id = 7
AND (p.parent_id IS NULL OR p.parent_id = 0);
-- İkisini birleştir (Union)
SELECT * FROM shop_products
WHERE category_id = 7
AND (parent_id IS NULL OR parent_id = 0)
UNION
SELECT p.*
FROM shop_products p
JOIN shop_categories c ON p.category_id = c.id
WHERE c.parent_id = 7
AND (p.parent_id IS NULL OR p.parent_id = 0);
-- Mevcut içeriği olan yedek parçalar
SELECT COUNT(*)
FROM shop_products
WHERE category_id = 7
AND (parent_id IS NULL OR parent_id = 0)
AND JSON_LENGTH(body, '$.tr') > 100;
-- Mevcut içeriği olmayan yedek parçalar
SELECT COUNT(*)
FROM shop_products
WHERE category_id = 7
AND (parent_id IS NULL OR parent_id = 0)
AND (body IS NULL OR JSON_LENGTH(body, '$.tr') < 100);
| Sıra | Dosya/Bileşen | Süre |
|---|---|---|
| 1 | ProductFilterService.php | 1 saat |
| 2 | ContentStrategyRouter.php | 2 saat |
| 3 | ContentValidator.php | 1 saat |
| 4 | ShopProductAIContentService.php | 3 saat |
| 5 | ShopProductImageGenerator.php | 2 saat |
| 6 | GenerateProductImagesJob.php | 1 saat |
| 7 | ProductAIContentGenerator Livewire | 4 saat |
| 8 | Test + Debug | 3 saat |
⏱️ Toplam Tahmini Süre: 17-19 saat