SamiKoen commited on
Commit
6e6115d
·
1 Parent(s): abca286

Copy all essential files from BF space to BF-WAB

Browse files

- Copy smart_warehouse_with_price.py (exact working version)
- Copy image_renderer.py for visual support
- Copy get_warehouse_fast.py for fast queries
- Copy warehouse_stock_finder.py
- Copy smart_warehouse.py
- Update app.py to use smart_warehouse_with_price instead of smart_warehouse_complete
- Now using exact same code as working BF space

app.py CHANGED
@@ -32,9 +32,9 @@ except ImportError:
32
 
33
  # Import GPT-5 powered smart warehouse search - complete BF algorithm
34
  try:
35
- from smart_warehouse_complete import get_warehouse_stock_smart_complete
36
  USE_GPT5_SEARCH = True
37
- logger.info("✅ GPT-5 complete smart warehouse (BF algorithm) loaded")
38
  except ImportError:
39
  USE_GPT5_SEARCH = False
40
  logger.info("❌ GPT-5 search not available")
@@ -72,7 +72,7 @@ def get_warehouse_stock(product_name):
72
  """B2B API'den mağaza stok bilgilerini çek - GPT-5 enhanced"""
73
  # Try GPT-5 complete smart search (BF algorithm)
74
  if USE_GPT5_SEARCH:
75
- gpt5_result = get_warehouse_stock_smart_complete(product_name)
76
  if gpt5_result and isinstance(gpt5_result, list):
77
  # Return directly if it's already formatted strings
78
  if all(isinstance(item, str) for item in gpt5_result):
@@ -1319,7 +1319,7 @@ async def health():
1319
  @app.get("/test-madone")
1320
  async def test_madone():
1321
  """Test MADONE search directly"""
1322
- from smart_warehouse_complete import get_warehouse_stock_smart_complete
1323
 
1324
  # Set a test API key if needed
1325
  import os
@@ -1327,7 +1327,7 @@ async def test_madone():
1327
  return {"error": "No OPENAI_API_KEY set"}
1328
 
1329
  try:
1330
- result = get_warehouse_stock_smart_complete("madone sl 6")
1331
  return {
1332
  "query": "madone sl 6",
1333
  "result": result if result else "No result",
 
32
 
33
  # Import GPT-5 powered smart warehouse search - complete BF algorithm
34
  try:
35
+ from smart_warehouse_with_price import get_warehouse_stock_smart_with_price
36
  USE_GPT5_SEARCH = True
37
+ logger.info("✅ GPT-5 complete smart warehouse with price (BF algorithm) loaded")
38
  except ImportError:
39
  USE_GPT5_SEARCH = False
40
  logger.info("❌ GPT-5 search not available")
 
72
  """B2B API'den mağaza stok bilgilerini çek - GPT-5 enhanced"""
73
  # Try GPT-5 complete smart search (BF algorithm)
74
  if USE_GPT5_SEARCH:
75
+ gpt5_result = get_warehouse_stock_smart_with_price(product_name)
76
  if gpt5_result and isinstance(gpt5_result, list):
77
  # Return directly if it's already formatted strings
78
  if all(isinstance(item, str) for item in gpt5_result):
 
1319
  @app.get("/test-madone")
1320
  async def test_madone():
1321
  """Test MADONE search directly"""
1322
+ from smart_warehouse_with_price import get_warehouse_stock_smart_with_price
1323
 
1324
  # Set a test API key if needed
1325
  import os
 
1327
  return {"error": "No OPENAI_API_KEY set"}
1328
 
1329
  try:
1330
+ result = get_warehouse_stock_smart_with_price("madone sl 6")
1331
  return {
1332
  "query": "madone sl 6",
1333
  "result": result if result else "No result",
get_warehouse_fast.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ultra fast warehouse stock getter using regex"""
2
+
3
+ def get_warehouse_stock(product_name):
4
+ """Super fast warehouse stock finder using regex instead of XML parsing"""
5
+ try:
6
+ import re
7
+ import requests
8
+
9
+ # Fetch XML
10
+ warehouse_url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php'
11
+ response = requests.get(warehouse_url, verify=False, timeout=7)
12
+
13
+ if response.status_code != 200:
14
+ return None
15
+
16
+ xml_text = response.text
17
+
18
+ # Turkish normalization
19
+ turkish_map = {'ı': 'i', 'ğ': 'g', 'ü': 'u', 'ş': 's', 'ö': 'o', 'ç': 'c', 'İ': 'i', 'I': 'i'}
20
+
21
+ def normalize_turkish(text):
22
+ text = text.lower()
23
+ for tr_char, en_char in turkish_map.items():
24
+ text = text.replace(tr_char, en_char)
25
+ return text
26
+
27
+ # Normalize search
28
+ search_name = normalize_turkish(product_name.strip())
29
+ search_name = search_name.replace('(2026)', '').replace('(2025)', '').strip()
30
+ search_words = search_name.split()
31
+
32
+ # Separate size from product words
33
+ size_words = ['s', 'm', 'l', 'xl', 'xs', 'xxl', 'ml']
34
+ size_indicators = ['beden', 'size', 'boy']
35
+
36
+ variant_filter = [w for w in search_words if w in size_words]
37
+ product_words = [w for w in search_words if w not in size_words and w not in size_indicators]
38
+
39
+ print(f"DEBUG - Looking for: {' '.join(product_words)}")
40
+ print(f"DEBUG - Size filter: {variant_filter}")
41
+
42
+ # Build exact pattern for common products
43
+ search_pattern = ' '.join(product_words).upper()
44
+
45
+ # Handle specific products
46
+ if 'madone' in product_words and 'sl' in product_words and '6' in product_words and 'gen' in product_words and '8' in product_words:
47
+ search_pattern = 'MADONE SL 6 GEN 8'
48
+ elif 'madone' in product_words and 'slr' in product_words and '7' in product_words:
49
+ search_pattern = 'MADONE SLR 7 GEN 8'
50
+ else:
51
+ # Generic pattern
52
+ search_pattern = search_pattern.replace('İ', 'I')
53
+
54
+ # Find all Product blocks with this name
55
+ # Using lazy quantifier .*? for efficiency
56
+ product_pattern = f'<Product>.*?<ProductName><!\\[CDATA\\[{re.escape(search_pattern)}\\]\\]></ProductName>.*?</Product>'
57
+ matches = re.findall(product_pattern, xml_text, re.DOTALL)
58
+
59
+ print(f"DEBUG - Found {len(matches)} products matching '{search_pattern}'")
60
+
61
+ # Process matches
62
+ warehouse_stock_map = {}
63
+
64
+ for match in matches:
65
+ # Extract variant if we need to filter by size
66
+ should_process = True
67
+
68
+ if variant_filter:
69
+ variant_match = re.search(r'<ProductVariant><!\\[CDATA\\[(.*?)\\]\\]></ProductVariant>', match)
70
+ if variant_match:
71
+ variant = variant_match.group(1)
72
+ size_wanted = variant_filter[0].upper()
73
+
74
+ # Check if variant starts with desired size
75
+ if variant.startswith(f'{size_wanted}-'):
76
+ print(f"DEBUG - Found matching variant: {variant}")
77
+ should_process = True
78
+ else:
79
+ should_process = False
80
+ else:
81
+ should_process = False
82
+
83
+ if should_process:
84
+ # Extract all warehouses with stock
85
+ warehouse_pattern = r'<Warehouse>.*?<Name><!\\[CDATA\\[(.*?)\\]\\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
86
+ warehouses = re.findall(warehouse_pattern, match, re.DOTALL)
87
+
88
+ for wh_name, wh_stock in warehouses:
89
+ try:
90
+ stock = int(wh_stock.strip())
91
+ if stock > 0:
92
+ if wh_name in warehouse_stock_map:
93
+ warehouse_stock_map[wh_name] += stock
94
+ else:
95
+ warehouse_stock_map[wh_name] = stock
96
+ except:
97
+ pass
98
+
99
+ # If we found a variant match, stop looking
100
+ if variant_filter and should_process:
101
+ break
102
+
103
+ print(f"DEBUG - Warehouse stock: {warehouse_stock_map}")
104
+
105
+ # Format results
106
+ if warehouse_stock_map:
107
+ all_warehouse_info = []
108
+ for warehouse_name, total_stock in warehouse_stock_map.items():
109
+ # Make store names more readable
110
+ if "Caddebostan" in warehouse_name or "CADDEBOSTAN" in warehouse_name:
111
+ display_name = "Caddebostan mağazası"
112
+ elif "Ortaköy" in warehouse_name or "ORTAKÖY" in warehouse_name:
113
+ display_name = "Ortaköy mağazası"
114
+ elif "Sarıyer" in warehouse_name:
115
+ display_name = "Sarıyer mağazası"
116
+ elif "Alsancak" in warehouse_name or "ALSANCAK" in warehouse_name or "İzmir" in warehouse_name:
117
+ display_name = "İzmir Alsancak mağazası"
118
+ elif "BAHCEKOY" in warehouse_name or "Bahçeköy" in warehouse_name:
119
+ display_name = "Bahçeköy mağazası"
120
+ else:
121
+ display_name = warehouse_name
122
+
123
+ all_warehouse_info.append(f"{display_name}: Mevcut")
124
+ return all_warehouse_info
125
+ else:
126
+ return ["Hiçbir mağazada mevcut değil"]
127
+
128
+ except Exception as e:
129
+ print(f"Warehouse stock error: {e}")
130
+ return None
image_renderer.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Ürün Resimlerini Sohbette Gösterme Sistemi
4
+ """
5
+
6
+ def round_price(price_str):
7
+ """Fiyatı yuvarlama formülüne göre yuvarla"""
8
+ try:
9
+ # TL ve diğer karakterleri temizle
10
+ price_clean = price_str.replace(' TL', '').replace(',', '.')
11
+ price_float = float(price_clean)
12
+
13
+ # Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
14
+ if price_float > 200000:
15
+ return str(round(price_float / 5000) * 5000)
16
+ # Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
17
+ elif price_float > 30000:
18
+ return str(round(price_float / 1000) * 1000)
19
+ # Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
20
+ elif price_float > 10000:
21
+ return str(round(price_float / 100) * 100)
22
+ # Diğer durumlarda en yakın 10'luk basamağa yuvarla
23
+ else:
24
+ return str(round(price_float / 10) * 10)
25
+ except (ValueError, TypeError):
26
+ return price_str
27
+
28
+ def format_message_with_images(message):
29
+ """Mesajdaki resim URL'lerini HTML formatına çevir"""
30
+ if "Ürün resmi:" not in message:
31
+ return message
32
+
33
+ lines = message.split('\n')
34
+ formatted_lines = []
35
+
36
+ for line in lines:
37
+ if line.startswith("Ürün resmi:"):
38
+ image_url = line.replace("Ürün resmi:", "").strip()
39
+ if image_url:
40
+ # HTML img tag'i oluştur
41
+ img_html = f"""
42
+ <div style="margin: 10px 0;">
43
+ <img src="{image_url}"
44
+ alt="Ürün Resmi"
45
+ style="max-width: 300px; max-height: 200px; border-radius: 8px; border: 1px solid #ddd; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"
46
+ onerror="this.style.display='none'">
47
+ </div>"""
48
+ formatted_lines.append(img_html)
49
+ else:
50
+ formatted_lines.append(line)
51
+ else:
52
+ formatted_lines.append(line)
53
+
54
+ return '\n'.join(formatted_lines)
55
+
56
+ def create_product_gallery(products_with_images):
57
+ """Birden fazla ürün için galeri oluştur"""
58
+ if not products_with_images:
59
+ return ""
60
+
61
+ gallery_html = """
62
+ <div style="display: flex; flex-wrap: wrap; gap: 15px; margin: 15px 0;">
63
+ """
64
+
65
+ for product in products_with_images:
66
+ name = product.get('name', 'Bilinmeyen')
67
+ price = product.get('price', 'Fiyat yok')
68
+ image_url = product.get('image_url', '')
69
+ product_url = product.get('product_url', '')
70
+
71
+ if image_url:
72
+ card_html = f"""
73
+ <div style="border: 1px solid #ddd; border-radius: 8px; padding: 10px; max-width: 200px; text-align: center; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
74
+ <img src="{image_url}"
75
+ alt="{name}"
76
+ style="max-width: 180px; max-height: 120px; border-radius: 4px; margin-bottom: 8px;"
77
+ onerror="this.style.display='none'">
78
+ <div style="font-size: 12px; font-weight: bold; margin-bottom: 4px;">{name}</div>
79
+ <div style="font-size: 11px; color: #666; margin-bottom: 8px;">{price}</div>
80
+ {f'<a href="{product_url}" target="_blank" style="font-size: 10px; color: #007bff; text-decoration: none;">Detaylı Bilgi</a>' if product_url else ''}
81
+ </div>"""
82
+ gallery_html += card_html
83
+
84
+ gallery_html += "</div>"
85
+ return gallery_html
86
+
87
+ def extract_product_info_for_gallery(message):
88
+ """Mesajdan ürün bilgilerini çıkarıp galeri formatına çevir"""
89
+ if "karşılaştır" in message.lower() or "öneri" in message.lower():
90
+ # Bu durumda galeri formatı kullan
91
+ lines = message.split('\n')
92
+ products = []
93
+
94
+ current_product = {}
95
+ for line in lines:
96
+ line = line.strip()
97
+ if line.startswith('•') and any(keyword in line.lower() for keyword in ['marlin', 'émonda', 'madone', 'domane', 'fuel', 'powerfly', 'fx']):
98
+ # Yeni ürün başladı
99
+ if current_product:
100
+ products.append(current_product)
101
+
102
+ # Ürün adı ve fiyatı parse et
103
+ parts = line.split(' - ')
104
+ name = parts[0].replace('•', '').strip()
105
+ price_raw = parts[1] if len(parts) > 1 else 'Fiyat yok'
106
+
107
+ # Fiyatı yuvarlama formülüne göre yuvarla
108
+ if price_raw != 'Fiyat yok':
109
+ price = round_price(price_raw) + ' TL'
110
+ else:
111
+ price = price_raw
112
+
113
+ current_product = {
114
+ 'name': name,
115
+ 'price': price,
116
+ 'image_url': '',
117
+ 'product_url': ''
118
+ }
119
+ elif "Ürün resmi:" in line and current_product:
120
+ current_product['image_url'] = line.replace("Ürün resmi:", "").strip()
121
+ elif "Ürün linki:" in line and current_product:
122
+ current_product['product_url'] = line.replace("Ürün linki:", "").strip()
123
+
124
+ # Son ürünü ekle
125
+ if current_product:
126
+ products.append(current_product)
127
+
128
+ if products:
129
+ gallery = create_product_gallery(products)
130
+ # Orijinal mesajdaki resim linklerini temizle
131
+ cleaned_message = message
132
+ for line in message.split('\n'):
133
+ if line.startswith("Ürün resmi:") or line.startswith("Ürün linki:"):
134
+ cleaned_message = cleaned_message.replace(line, "")
135
+
136
+ return cleaned_message.strip() + "\n\n" + gallery
137
+
138
+ return format_message_with_images(message)
139
+
140
+ def should_use_gallery_format(message):
141
+ """Mesajın galeri formatı kullanması gerekip gerekmediğini kontrol et"""
142
+ gallery_keywords = ["karşılaştır", "öneri", "seçenek", "alternatif", "bütçe"]
143
+ return any(keyword in message.lower() for keyword in gallery_keywords)
smart_warehouse.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Smart warehouse stock finder using GPT-5's intelligence"""
2
+
3
+ import requests
4
+ import re
5
+ import os
6
+ import json
7
+
8
+ def get_warehouse_stock_smart(user_message, previous_result=None):
9
+ """Let GPT-5 intelligently find products or filter by warehouse"""
10
+
11
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
12
+
13
+ # Check if user is asking about specific warehouse
14
+ warehouse_keywords = {
15
+ 'caddebostan': 'Caddebostan',
16
+ 'ortaköy': 'Ortaköy',
17
+ 'ortakoy': 'Ortaköy',
18
+ 'alsancak': 'Alsancak',
19
+ 'izmir': 'Alsancak',
20
+ 'bahçeköy': 'Bahçeköy',
21
+ 'bahcekoy': 'Bahçeköy'
22
+ }
23
+
24
+ user_lower = user_message.lower()
25
+ asked_warehouse = None
26
+ for keyword, warehouse in warehouse_keywords.items():
27
+ if keyword in user_lower:
28
+ asked_warehouse = warehouse
29
+ break
30
+
31
+ # Get XML data with retry
32
+ xml_text = None
33
+ for attempt in range(3): # Try 3 times
34
+ try:
35
+ url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php'
36
+ timeout_val = 10 + (attempt * 5) # Increase timeout on each retry: 10, 15, 20
37
+ response = requests.get(url, verify=False, timeout=timeout_val)
38
+ xml_text = response.text
39
+ print(f"DEBUG - XML fetched: {len(xml_text)} characters (attempt {attempt+1})")
40
+ break
41
+ except requests.exceptions.Timeout:
42
+ print(f"XML fetch timeout (attempt {attempt+1}/3, timeout={timeout_val}s)")
43
+ if attempt == 2:
44
+ print("All attempts failed - timeout")
45
+ return None
46
+ except Exception as e:
47
+ print(f"XML fetch error: {e}")
48
+ return None
49
+
50
+ # Extract just product blocks to reduce token usage
51
+ product_pattern = r'<Product>(.*?)</Product>'
52
+ all_products = re.findall(product_pattern, xml_text, re.DOTALL)
53
+
54
+ # Create a simplified product list for GPT
55
+ products_summary = []
56
+ for i, product_block in enumerate(all_products):
57
+ name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block)
58
+ variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block)
59
+
60
+ if name_match:
61
+ # Check warehouse stock for this product
62
+ warehouses_with_stock = []
63
+ warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
64
+ warehouses = re.findall(warehouse_regex, product_block, re.DOTALL)
65
+
66
+ for wh_name, wh_stock in warehouses:
67
+ try:
68
+ if int(wh_stock.strip()) > 0:
69
+ warehouses_with_stock.append(wh_name)
70
+ except:
71
+ pass
72
+
73
+ product_info = {
74
+ "index": i,
75
+ "name": name_match.group(1),
76
+ "variant": variant_match.group(1) if variant_match else "",
77
+ "warehouses": warehouses_with_stock
78
+ }
79
+ products_summary.append(product_info)
80
+
81
+ # If user is asking about specific warehouse, include that in prompt
82
+ warehouse_filter = ""
83
+ if asked_warehouse:
84
+ warehouse_filter = f"\nIMPORTANT: User is asking specifically about {asked_warehouse} warehouse. Only return products available in that warehouse."
85
+
86
+ # Let GPT-5 find ALL matching products
87
+ smart_prompt = f"""User is asking: "{user_message}"
88
+
89
+ Find ALL products that match this query from the list below.
90
+ If user asks about specific size (S, M, L, XL, XXL, SMALL, MEDIUM, LARGE, X-LARGE), return only that size.
91
+ If user asks generally (without size), return ALL variants of the product.
92
+ {warehouse_filter}
93
+
94
+ IMPORTANT BRAND AND PRODUCT TYPE RULES:
95
+ - GOBIK: Spanish textile brand we import. When user asks about "gobik", return ALL products with "GOBIK" in the name.
96
+ - Product names contain type information: FORMA (jersey/cycling shirt), TAYT (tights), İÇLİK (base layer), YAĞMURLUK (raincoat), etc.
97
+ - Understand Turkish/English terms:
98
+ * "erkek forma" / "men's jersey" -> Find products with FORMA in name
99
+ * "tayt" / "tights" -> Find products with TAYT in name
100
+ * "içlik" / "base layer" -> Find products with İÇLİK in name
101
+ * "yağmurluk" / "raincoat" -> Find products with YAĞMURLUK in name
102
+ - Gender: UNISEX means for both men and women. If no gender specified, it's typically men's.
103
+ - Be smart: "erkek forma" should find all FORMA products (excluding women-specific if any)
104
+
105
+ Products list (with warehouse availability):
106
+ {json.dumps(products_summary, ensure_ascii=False, indent=2)}
107
+
108
+ Return index numbers of ALL matching products as comma-separated list (e.g., "5,8,12,15").
109
+ If no products found, return: -1
110
+
111
+ Examples:
112
+ - "madone sl 6 var mı" -> Return ALL Madone SL 6 variants
113
+ - "erkek forma" -> Return all products with FORMA in name
114
+ - "gobik tayt" -> Return all GOBIK products with TAYT in name
115
+ - "içlik var mı" -> Return all products with İÇLİK in name
116
+ - "gobik erkek forma" -> Return all GOBIK products with FORMA in name
117
+ - "yağmurluk medium" -> Return all YAĞMURLUK products in MEDIUM size"""
118
+
119
+ headers = {
120
+ "Content-Type": "application/json",
121
+ "Authorization": f"Bearer {OPENAI_API_KEY}"
122
+ }
123
+
124
+ payload = {
125
+ "model": "gpt-5-chat-latest",
126
+ "messages": [
127
+ {"role": "system", "content": "You are a product matcher. Find ALL matching products. Return only index numbers."},
128
+ {"role": "user", "content": smart_prompt}
129
+ ],
130
+ "temperature": 0,
131
+ "max_tokens": 100
132
+ }
133
+
134
+ try:
135
+ response = requests.post(
136
+ "https://api.openai.com/v1/chat/completions",
137
+ headers=headers,
138
+ json=payload,
139
+ timeout=10
140
+ )
141
+
142
+ if response.status_code == 200:
143
+ result = response.json()
144
+ indices_str = result['choices'][0]['message']['content'].strip()
145
+
146
+ if indices_str == "-1":
147
+ return ["Ürün bulunamadı"]
148
+
149
+ try:
150
+ # Parse multiple indices
151
+ indices = [int(idx.strip()) for idx in indices_str.split(',')]
152
+
153
+ # Collect all matching products
154
+ all_variants = []
155
+ warehouse_stock = {}
156
+
157
+ for idx in indices:
158
+ if 0 <= idx < len(all_products):
159
+ product_block = all_products[idx]
160
+
161
+ # Get product name and variant
162
+ name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block)
163
+ variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block)
164
+
165
+ if name_match:
166
+ product_name = name_match.group(1)
167
+ variant = variant_match.group(1) if variant_match else ""
168
+
169
+ # Track this variant
170
+ variant_info = {
171
+ 'name': product_name,
172
+ 'variant': variant,
173
+ 'warehouses': []
174
+ }
175
+
176
+ # Get warehouse stock
177
+ warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
178
+ warehouses = re.findall(warehouse_regex, product_block, re.DOTALL)
179
+
180
+ for wh_name, wh_stock in warehouses:
181
+ try:
182
+ stock = int(wh_stock.strip())
183
+ if stock > 0:
184
+ display_name = format_warehouse_name(wh_name)
185
+ variant_info['warehouses'].append({
186
+ 'name': display_name,
187
+ 'stock': stock
188
+ })
189
+
190
+ # Track total stock per warehouse
191
+ if display_name not in warehouse_stock:
192
+ warehouse_stock[display_name] = 0
193
+ warehouse_stock[display_name] += stock
194
+ except:
195
+ pass
196
+
197
+ if variant_info['warehouses']: # Only add if has stock
198
+ all_variants.append(variant_info)
199
+
200
+ # Format result
201
+ result = []
202
+
203
+ if asked_warehouse:
204
+ # Filter for specific warehouse
205
+ warehouse_variants = []
206
+ for variant in all_variants:
207
+ for wh in variant['warehouses']:
208
+ if asked_warehouse in wh['name']:
209
+ warehouse_variants.append({
210
+ 'name': variant['name'],
211
+ 'variant': variant['variant'],
212
+ 'stock': wh['stock']
213
+ })
214
+
215
+ if warehouse_variants:
216
+ result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında mevcut:")
217
+ for v in warehouse_variants:
218
+ result.append(f"• {v['name']} ({v['variant']})")
219
+ else:
220
+ result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında bu ürün mevcut değil")
221
+ else:
222
+ # Show all variants and warehouses
223
+ if all_variants:
224
+ result.append(f"Bulunan {len(all_variants)} varyant:")
225
+
226
+ # Show ALL variants (not just first 5)
227
+ for variant in all_variants:
228
+ variant_text = f" ({variant['variant']})" if variant['variant'] else ""
229
+ result.append(f"• {variant['name']}{variant_text}")
230
+
231
+ result.append("")
232
+ result.append("Mağaza stok durumu:")
233
+ for warehouse, total_stock in sorted(warehouse_stock.items()):
234
+ result.append(f"• {warehouse}: Mevcut")
235
+ else:
236
+ result.append("Hiçbir mağazada stok yok")
237
+
238
+ return result
239
+
240
+ except (ValueError, IndexError) as e:
241
+ print(f"DEBUG - Error parsing indices: {e}")
242
+ return None
243
+ else:
244
+ print(f"GPT API error: {response.status_code}")
245
+ return None
246
+
247
+ except Exception as e:
248
+ print(f"Error calling GPT: {e}")
249
+ return None
250
+
251
+ def format_warehouse_name(wh_name):
252
+ """Format warehouse name nicely"""
253
+ if "CADDEBOSTAN" in wh_name:
254
+ return "Caddebostan mağazası"
255
+ elif "ORTAKÖY" in wh_name:
256
+ return "Ortaköy mağazası"
257
+ elif "ALSANCAK" in wh_name:
258
+ return "İzmir Alsancak mağazası"
259
+ elif "BAHCEKOY" in wh_name or "BAHÇEKÖY" in wh_name:
260
+ return "Bahçeköy mağazası"
261
+ else:
262
+ return wh_name.replace("MAGAZA DEPO", "").strip()
smart_warehouse_with_price.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Smart warehouse stock finder with price and link information"""
2
+
3
+ import requests
4
+ import re
5
+ import os
6
+ import json
7
+ import xml.etree.ElementTree as ET
8
+
9
+ def get_product_price_and_link(product_name, variant=None):
10
+ """Get price and link from Trek website XML"""
11
+ try:
12
+ # Get Trek product catalog
13
+ url = 'https://www.trekbisiklet.com.tr/output/8582384479'
14
+ response = requests.get(url, verify=False, timeout=10)
15
+
16
+ if response.status_code != 200:
17
+ return None, None
18
+
19
+ root = ET.fromstring(response.content)
20
+
21
+ # Normalize search terms
22
+ search_name = product_name.lower()
23
+ search_variant = variant.lower() if variant else ""
24
+
25
+ # Turkish character normalization
26
+ tr_map = {'ı': 'i', 'ğ': 'g', 'ü': 'u', 'ş': 's', 'ö': 'o', 'ç': 'c'}
27
+ for tr, en in tr_map.items():
28
+ search_name = search_name.replace(tr, en)
29
+ search_variant = search_variant.replace(tr, en)
30
+
31
+ best_match = None
32
+ best_score = 0
33
+
34
+ for item in root.findall('item'):
35
+ # Get product name
36
+ rootlabel_elem = item.find('rootlabel')
37
+ if rootlabel_elem is None or not rootlabel_elem.text:
38
+ continue
39
+
40
+ item_name = rootlabel_elem.text.lower()
41
+ for tr, en in tr_map.items():
42
+ item_name = item_name.replace(tr, en)
43
+
44
+ # Calculate match score
45
+ score = 0
46
+ name_parts = search_name.split()
47
+ for part in name_parts:
48
+ if part in item_name:
49
+ score += 1
50
+
51
+ # Check variant if specified
52
+ if variant and search_variant in item_name:
53
+ score += 2 # Variant match is important
54
+
55
+ if score > best_score:
56
+ best_score = score
57
+ best_match = item
58
+
59
+ if best_match and best_score > 0:
60
+ # Extract price
61
+ price_elem = best_match.find('priceTaxWithCur')
62
+ price = price_elem.text if price_elem is not None and price_elem.text else None
63
+
64
+ # Round price
65
+ if price:
66
+ try:
67
+ price_float = float(price)
68
+ if price_float > 200000:
69
+ rounded = round(price_float / 5000) * 5000
70
+ price = f"{int(rounded):,}".replace(',', '.') + " TL"
71
+ elif price_float > 30000:
72
+ rounded = round(price_float / 1000) * 1000
73
+ price = f"{int(rounded):,}".replace(',', '.') + " TL"
74
+ elif price_float > 10000:
75
+ rounded = round(price_float / 100) * 100
76
+ price = f"{int(rounded):,}".replace(',', '.') + " TL"
77
+ else:
78
+ rounded = round(price_float / 10) * 10
79
+ price = f"{int(rounded):,}".replace(',', '.') + " TL"
80
+ except:
81
+ price = f"{price} TL"
82
+
83
+ # Extract link (field name is productLink, not productUrl!)
84
+ link_elem = best_match.find('productLink')
85
+ link = link_elem.text if link_elem is not None and link_elem.text else None
86
+
87
+ return price, link
88
+
89
+ return None, None
90
+
91
+ except Exception as e:
92
+ print(f"Error getting price/link: {e}")
93
+ return None, None
94
+
95
+ def get_warehouse_stock_smart_with_price(user_message, previous_result=None):
96
+ """Enhanced smart warehouse search with price and link info"""
97
+
98
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
99
+
100
+ # Check if user is asking about specific warehouse
101
+ warehouse_keywords = {
102
+ 'caddebostan': 'Caddebostan',
103
+ 'ortaköy': 'Ortaköy',
104
+ 'ortakoy': 'Ortaköy',
105
+ 'alsancak': 'Alsancak',
106
+ 'izmir': 'Alsancak',
107
+ 'bahçeköy': 'Bahçeköy',
108
+ 'bahcekoy': 'Bahçeköy'
109
+ }
110
+
111
+ user_lower = user_message.lower()
112
+ asked_warehouse = None
113
+ for keyword, warehouse in warehouse_keywords.items():
114
+ if keyword in user_lower:
115
+ asked_warehouse = warehouse
116
+ break
117
+
118
+ # Get XML data with retry
119
+ xml_text = None
120
+ for attempt in range(3):
121
+ try:
122
+ url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php'
123
+ timeout_val = 10 + (attempt * 5)
124
+ response = requests.get(url, verify=False, timeout=timeout_val)
125
+ xml_text = response.text
126
+ print(f"DEBUG - XML fetched: {len(xml_text)} characters (attempt {attempt+1})")
127
+ break
128
+ except requests.exceptions.Timeout:
129
+ print(f"XML fetch timeout (attempt {attempt+1}/3, timeout={timeout_val}s)")
130
+ if attempt == 2:
131
+ print("All attempts failed - timeout")
132
+ return None
133
+ except Exception as e:
134
+ print(f"XML fetch error: {e}")
135
+ return None
136
+
137
+ # Extract product blocks
138
+ product_pattern = r'<Product>(.*?)</Product>'
139
+ all_products = re.findall(product_pattern, xml_text, re.DOTALL)
140
+
141
+ # Create simplified product list for GPT
142
+ products_summary = []
143
+ for i, product_block in enumerate(all_products):
144
+ name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block)
145
+ variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block)
146
+
147
+ if name_match:
148
+ warehouses_with_stock = []
149
+ warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
150
+ warehouses = re.findall(warehouse_regex, product_block, re.DOTALL)
151
+
152
+ for wh_name, wh_stock in warehouses:
153
+ try:
154
+ if int(wh_stock.strip()) > 0:
155
+ warehouses_with_stock.append(wh_name)
156
+ except:
157
+ pass
158
+
159
+ product_info = {
160
+ "index": i,
161
+ "name": name_match.group(1),
162
+ "variant": variant_match.group(1) if variant_match else "",
163
+ "warehouses": warehouses_with_stock
164
+ }
165
+ products_summary.append(product_info)
166
+
167
+ # Prepare warehouse filter if needed
168
+ warehouse_filter = ""
169
+ if asked_warehouse:
170
+ warehouse_filter = f"\nIMPORTANT: User is asking specifically about {asked_warehouse} warehouse. Only return products available in that warehouse."
171
+
172
+ # GPT-5 prompt with enhanced instructions
173
+ smart_prompt = f"""User is asking: "{user_message}"
174
+
175
+ Find ALL products that match this query from the list below.
176
+ If user asks about specific size (S, M, L, XL, XXL, SMALL, MEDIUM, LARGE, X-LARGE), return only that size.
177
+ If user asks generally (without size), return ALL variants of the product.
178
+ {warehouse_filter}
179
+
180
+ IMPORTANT BRAND AND PRODUCT TYPE RULES:
181
+ - GOBIK: Spanish textile brand we import. When user asks about "gobik", return ALL products with "GOBIK" in the name.
182
+ - Product names contain type information: FORMA (jersey/cycling shirt), TAYT (tights), İÇLİK (base layer), YAĞMURLUK (raincoat), etc.
183
+ - Understand Turkish/English terms:
184
+ * "erkek forma" / "men's jersey" -> Find products with FORMA in name
185
+ * "tayt" / "tights" -> Find products with TAYT in name
186
+ * "içlik" / "base layer" -> Find products with İÇLİK in name
187
+ * "yağmurluk" / "raincoat" -> Find products with YAĞMURLUK in name
188
+ - Gender: UNISEX means for both men and women. If no gender specified, it's typically men's.
189
+
190
+ Products list (with warehouse availability):
191
+ {json.dumps(products_summary, ensure_ascii=False, indent=2)}
192
+
193
+ Return ONLY index numbers of ALL matching products as comma-separated list (e.g., "5,8,12,15").
194
+ If no products found, return ONLY: -1
195
+ DO NOT return empty string or any explanation, ONLY numbers or -1
196
+
197
+ Examples of correct responses:
198
+ - "2,5,8,12,15,20" (multiple products found)
199
+ - "45" (single product found)
200
+ - "-1" (no products found)"""
201
+
202
+ headers = {
203
+ "Content-Type": "application/json",
204
+ "Authorization": f"Bearer {OPENAI_API_KEY}"
205
+ }
206
+
207
+ payload = {
208
+ "model": "gpt-5-chat-latest",
209
+ "messages": [
210
+ {"role": "system", "content": "You are a product matcher. Find ALL matching products. Return only index numbers."},
211
+ {"role": "user", "content": smart_prompt}
212
+ ],
213
+ "temperature": 0,
214
+ "max_tokens": 100
215
+ }
216
+
217
+ try:
218
+ response = requests.post(
219
+ "https://api.openai.com/v1/chat/completions",
220
+ headers=headers,
221
+ json=payload,
222
+ timeout=10
223
+ )
224
+
225
+ if response.status_code == 200:
226
+ result = response.json()
227
+ indices_str = result['choices'][0]['message']['content'].strip()
228
+
229
+ print(f"DEBUG - GPT-5 response: '{indices_str}'")
230
+
231
+ # Handle empty response
232
+ if not indices_str or indices_str == "-1":
233
+ return ["Ürün bulunamadı"]
234
+
235
+ try:
236
+ # Filter out empty strings and parse indices
237
+ indices = []
238
+ for idx in indices_str.split(','):
239
+ idx = idx.strip()
240
+ if idx and idx.isdigit():
241
+ indices.append(int(idx))
242
+
243
+ # Collect all matching products with price/link
244
+ all_variants = []
245
+ warehouse_stock = {}
246
+
247
+ for idx in indices:
248
+ if 0 <= idx < len(all_products):
249
+ product_block = all_products[idx]
250
+
251
+ # Get product details
252
+ name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block)
253
+ variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block)
254
+
255
+ if name_match:
256
+ product_name = name_match.group(1)
257
+ variant = variant_match.group(1) if variant_match else ""
258
+
259
+ # Get price and link from Trek website
260
+ price, link = get_product_price_and_link(product_name, variant)
261
+
262
+ variant_info = {
263
+ 'name': product_name,
264
+ 'variant': variant,
265
+ 'price': price,
266
+ 'link': link,
267
+ 'warehouses': []
268
+ }
269
+
270
+ # Get warehouse stock
271
+ warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
272
+ warehouses = re.findall(warehouse_regex, product_block, re.DOTALL)
273
+
274
+ for wh_name, wh_stock in warehouses:
275
+ try:
276
+ stock = int(wh_stock.strip())
277
+ if stock > 0:
278
+ display_name = format_warehouse_name(wh_name)
279
+ variant_info['warehouses'].append({
280
+ 'name': display_name,
281
+ 'stock': stock
282
+ })
283
+
284
+ if display_name not in warehouse_stock:
285
+ warehouse_stock[display_name] = 0
286
+ warehouse_stock[display_name] += stock
287
+ except:
288
+ pass
289
+
290
+ if variant_info['warehouses']:
291
+ all_variants.append(variant_info)
292
+
293
+ # Format result
294
+ result = []
295
+
296
+ if asked_warehouse:
297
+ # Filter for specific warehouse
298
+ warehouse_variants = []
299
+ for variant in all_variants:
300
+ for wh in variant['warehouses']:
301
+ if asked_warehouse in wh['name']:
302
+ warehouse_variants.append(variant)
303
+ break
304
+
305
+ if warehouse_variants:
306
+ result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında mevcut:")
307
+ for v in warehouse_variants:
308
+ variant_text = f" ({v['variant']})" if v['variant'] else ""
309
+ result.append(f"• {v['name']}{variant_text}")
310
+ if v['price']:
311
+ result.append(f" Fiyat: {v['price']}")
312
+ if v['link']:
313
+ result.append(f" Link: {v['link']}")
314
+ else:
315
+ result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında bu ürün mevcut değil")
316
+ else:
317
+ # Show all variants
318
+ if all_variants:
319
+ # Group by product name for cleaner display
320
+ product_groups = {}
321
+ for variant in all_variants:
322
+ if variant['name'] not in product_groups:
323
+ product_groups[variant['name']] = []
324
+ product_groups[variant['name']].append(variant)
325
+
326
+ result.append(f"Bulunan ürünler:")
327
+
328
+ for product_name, variants in product_groups.items():
329
+ result.append(f"\n{product_name}:")
330
+
331
+ # Show first variant's price and link (usually same for all variants)
332
+ if variants[0]['price']:
333
+ result.append(f"Fiyat: {variants[0]['price']}")
334
+ if variants[0]['link']:
335
+ result.append(f"Link: {variants[0]['link']}")
336
+
337
+ # Show variants and their availability
338
+ for v in variants:
339
+ if v['variant']:
340
+ warehouses_str = ", ".join([w['name'].replace(' mağazası', '') for w in v['warehouses']])
341
+ result.append(f"• {v['variant']}: {warehouses_str}")
342
+
343
+ else:
344
+ result.append("Hiçbir mağazada stok yok")
345
+
346
+ return result
347
+
348
+ except (ValueError, IndexError) as e:
349
+ print(f"DEBUG - Error parsing indices: {e}")
350
+ return None
351
+ else:
352
+ print(f"GPT API error: {response.status_code}")
353
+ return None
354
+
355
+ except Exception as e:
356
+ print(f"Error calling GPT: {e}")
357
+ return None
358
+
359
+ def format_warehouse_name(wh_name):
360
+ """Format warehouse name nicely"""
361
+ if "CADDEBOSTAN" in wh_name:
362
+ return "Caddebostan mağazası"
363
+ elif "ORTAKÖY" in wh_name:
364
+ return "Ortaköy mağazası"
365
+ elif "ALSANCAK" in wh_name:
366
+ return "İzmir Alsancak mağazası"
367
+ elif "BAHCEKOY" in wh_name or "BAHÇEKÖY" in wh_name:
368
+ return "Bahçeköy mağazası"
369
+ else:
370
+ return wh_name.replace("MAGAZA DEPO", "").strip()
warehouse_stock_finder.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ultra simple and fast warehouse stock finder"""
2
+
3
+ def get_warehouse_stock(product_name):
4
+ """Find warehouse stock FAST - no XML parsing, just regex"""
5
+ try:
6
+ import re
7
+ import requests
8
+
9
+ # Get XML
10
+ url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php'
11
+ response = requests.get(url, verify=False, timeout=7)
12
+ xml_text = response.text
13
+
14
+ # Turkish normalize
15
+ def normalize(text):
16
+ tr_map = {'ı': 'i', 'ğ': 'g', 'ü': 'u', 'ş': 's', 'ö': 'o', 'ç': 'c', 'İ': 'i', 'I': 'i'}
17
+ text = text.lower()
18
+ for tr, en in tr_map.items():
19
+ text = text.replace(tr, en)
20
+ return text
21
+
22
+ # Parse query
23
+ query = normalize(product_name.strip()).replace('(2026)', '').replace('(2025)', '').strip()
24
+ words = query.split()
25
+
26
+ # Find size
27
+ sizes = ['s', 'm', 'l', 'xl', 'xs', 'xxl', 'ml']
28
+ size = next((w for w in words if w in sizes), None)
29
+ product_words = [w for w in words if w not in sizes and w not in ['beden', 'size', 'boy']]
30
+
31
+ # Build search pattern
32
+ if 'madone' in product_words and 'sl' in product_words and '6' in product_words:
33
+ pattern = 'MADONE SL 6 GEN 8'
34
+ else:
35
+ pattern = ' '.join(product_words).upper()
36
+
37
+ print(f"DEBUG - Searching: {pattern}, Size: {size}")
38
+
39
+ # Search for product + variant combo
40
+ if size:
41
+ # Direct search for product with specific size
42
+ size_pattern = f'{size.upper()}-'
43
+
44
+ # Find all occurrences of the product name
45
+ import re
46
+ product_regex = f'<Product>.*?<ProductName><!\\[CDATA\\[{re.escape(pattern)}\\]\\]></ProductName>.*?<ProductVariant><!\\[CDATA\\[{size_pattern}.*?\\]\\]></ProductVariant>.*?</Product>'
47
+
48
+ match = re.search(product_regex, xml_text, re.DOTALL)
49
+
50
+ if match:
51
+ product_block = match.group(0)
52
+ print(f"DEBUG - Found product with {size_pattern} variant")
53
+
54
+ # Extract warehouses
55
+ warehouse_info = []
56
+ warehouse_regex = r'<Warehouse>.*?<Name><!\\[CDATA\\[(.*?)\\]\\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>'
57
+ warehouses = re.findall(warehouse_regex, product_block, re.DOTALL)
58
+
59
+ for wh_name, wh_stock in warehouses:
60
+ try:
61
+ stock = int(wh_stock.strip())
62
+ if stock > 0:
63
+ # Format name
64
+ if "CADDEBOSTAN" in wh_name:
65
+ display = "Caddebostan mağazası"
66
+ elif "ORTAKÖY" in wh_name:
67
+ display = "Ortaköy mağazası"
68
+ elif "ALSANCAK" in wh_name:
69
+ display = "İzmir Alsancak mağazası"
70
+ elif "BAHCEKOY" in wh_name or "BAHÇEKÖY" in wh_name:
71
+ display = "Bahçeköy mağazası"
72
+ else:
73
+ display = wh_name
74
+
75
+ warehouse_info.append(f"{display}: Mevcut")
76
+ except:
77
+ pass
78
+
79
+ return warehouse_info if warehouse_info else ["Hiçbir mağazada mevcut değil"]
80
+ else:
81
+ print(f"DEBUG - No {size_pattern} variant found for {pattern}")
82
+ return ["Hiçbir mağazada mevcut değil"]
83
+ else:
84
+ # No size filter - get all stock
85
+ return ["Beden bilgisi belirtilmedi"]
86
+
87
+ except Exception as e:
88
+ print(f"Error: {e}")
89
+ return None