SamiKoen Claude commited on
Commit
d08707a
·
1 Parent(s): a584ddc

restore: revert to backup system from today (before Combined API)

Browse files

- Restored app.py from app_backup_before_combined_api_20250905_2207.py
- Restored smart_warehouse_with_price.py from backup
- Back to GPT-5 enhanced warehouse search system
- Combined API experiments removed, returning to stable system

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>

Files changed (1) hide show
  1. app.py +187 -52
app.py CHANGED
@@ -32,24 +32,11 @@ USE_IMPROVED_SEARCH = False
32
  # print("Improved WhatsApp chatbot not available, using basic search")
33
  # USE_IMPROVED_SEARCH = False
34
 
35
- # Import Combined API search - yeni tek API sistemi
36
- try:
37
- from combined_api_search import (
38
- get_warehouse_stock_combined_api,
39
- search_products_combined_api,
40
- format_product_result_whatsapp
41
- )
42
- USE_COMBINED_API = True
43
- logger.info("✅ Combined API search system loaded")
44
- except ImportError:
45
- USE_COMBINED_API = False
46
- logger.info("❌ Combined API search not available")
47
-
48
- # Import GPT-5 powered smart warehouse search - backup olarak
49
  try:
50
  from smart_warehouse_with_price import get_warehouse_stock_smart_with_price
51
  USE_GPT5_SEARCH = True
52
- logger.info("✅ GPT-5 warehouse search loaded as backup")
53
  except ImportError:
54
  USE_GPT5_SEARCH = False
55
  logger.info("❌ GPT-5 search not available")
@@ -137,29 +124,188 @@ else:
137
 
138
  # Mağaza stok bilgilerini çekme fonksiyonu
139
  def get_warehouse_stock(product_name):
140
- """Combined API'den stok bilgilerini çek - yeni tek API sistemi"""
141
- logger.info(f"🔍 get_warehouse_stock called for: {product_name}")
142
- logger.info(f"🔧 USE_COMBINED_API = {USE_COMBINED_API}")
143
-
144
- # SADECE Combined API kullan - diğer sistemleri devre dışı bırak
145
- if USE_COMBINED_API:
146
  try:
147
- logger.info(f"🚀 Calling get_warehouse_stock_combined_api for: {product_name}")
148
- combined_result = get_warehouse_stock_combined_api(product_name)
149
- logger.info(f"📊 Combined API result: {combined_result}")
150
- if combined_result and combined_result != ["Ürün bulunamadı"]:
151
- logger.info(f"✅ Combined API ile bulundu: {product_name}")
152
- return combined_result
153
- else:
154
- logger.info(f"❌ Combined API'de bulunamadı: {product_name}")
155
- return ["Ürün bulunamadı"]
 
 
 
 
 
 
 
 
 
 
 
156
  except Exception as e:
157
- logger.error(f" Combined API search error: {e}")
158
- return ["Combined API hatası"]
159
 
160
- # Combined API yoksa hata mesajı döndür
161
- logger.error(f"❌ Combined API not available!")
162
- return ["Combined API system not available"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
  # Trek bisiklet ürünlerini çekme - DÜZELTİLMİŞ VERSİYON
165
  try:
@@ -967,14 +1113,11 @@ def process_whatsapp_message_with_memory(user_message, phone_number):
967
  except Exception as e:
968
  logger.error(f"❌ BF Space: Improved search error: {e}")
969
 
970
- # Fallback to Combined API search if improved search didn't work
971
  if not product_found_improved:
972
  # Check if message seems to be asking about products
973
  product_keywords = ['fiyat', 'kaç', 'stok', 'var mı', 'mevcut', 'bisiklet', 'bike',
974
- 'trek', 'model', 'beden', 'renk', 'mağaza', 'nerede', 'hangi',
975
- 'marlin', 'madone', 'fuel', 'domane', 'slash', 'remedy', 'session', 'procaliber',
976
- 'roscoe', 'supercommuter', 'allant', 'verve', 'dual sport', 'fx', 'checkpoint',
977
- 'émonda', 'speed concept', 'boone', 'crockett', 'stache', 'farley']
978
 
979
  # Common non-product responses
980
  non_product_responses = ['süper', 'harika', 'güzel', 'teşekkür', 'tamam', 'olur',
@@ -983,36 +1126,28 @@ def process_whatsapp_message_with_memory(user_message, phone_number):
983
  is_product_query = False
984
  lower_message = user_message.lower()
985
 
986
- logger.info(f"🔍 Product query detection for: '{user_message}'")
987
- logger.info(f"🔤 Lower message: '{lower_message}'")
988
-
989
  # Check if it's likely a product query
990
  if any(keyword in lower_message for keyword in product_keywords):
991
  is_product_query = True
992
- logger.info(f"✅ Product query detected via keywords")
993
  # Check if it's NOT a simple response
994
  elif lower_message not in non_product_responses and len(lower_message.split()) > 1:
995
  # Multi-word queries might be product searches
996
  is_product_query = True
997
- logger.info(f"✅ Product query detected via multi-word rule")
998
  # Single short words are usually not products
999
  elif len(lower_message.split()) == 1 and len(lower_message) < 6:
1000
  is_product_query = False
1001
- logger.info(f"❌ Product query rejected - single short word")
1002
-
1003
- logger.info(f"🎯 Final is_product_query: {is_product_query}")
1004
 
1005
  if is_product_query:
1006
- # SADECE Combined API kullan
1007
- logger.info("📦 Using Combined API search")
1008
  warehouse_result = get_warehouse_stock(user_message)
1009
  if warehouse_result and warehouse_result != ['Ürün bulunamadı']:
1010
  warehouse_response = "\n".join(warehouse_result)
1011
  messages.append({
1012
  "role": "system",
1013
- "content": f"COMBINED API STOK BİLGİSİ:\n{warehouse_response}\n\nBu bilgileri kullanarak kullanıcıya yardımcı ol. Fiyat, stok ve resim bilgilerini AYNEN kullan."
1014
  })
1015
- logger.info(f"✅ Combined API stock info added: {warehouse_response[:200]}...")
1016
  else:
1017
  logger.info(f"🚫 Skipping product search for: '{user_message}'")
1018
 
 
32
  # print("Improved WhatsApp chatbot not available, using basic search")
33
  # USE_IMPROVED_SEARCH = False
34
 
35
+ # Import GPT-5 powered smart warehouse search - complete BF algorithm
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  try:
37
  from smart_warehouse_with_price import get_warehouse_stock_smart_with_price
38
  USE_GPT5_SEARCH = True
39
+ logger.info("✅ GPT-5 complete smart warehouse with price (BF algorithm) loaded")
40
  except ImportError:
41
  USE_GPT5_SEARCH = False
42
  logger.info("❌ GPT-5 search not available")
 
124
 
125
  # Mağaza stok bilgilerini çekme fonksiyonu
126
  def get_warehouse_stock(product_name):
127
+ """B2B API'den mağaza stok bilgilerini çek - GPT-5 enhanced"""
128
+ # Try GPT-5 complete smart search (BF algorithm)
129
+ if USE_GPT5_SEARCH:
 
 
 
130
  try:
131
+ gpt5_result = get_warehouse_stock_smart_with_price(product_name)
132
+ if gpt5_result and isinstance(gpt5_result, list):
133
+ # Return directly if it's already formatted strings
134
+ if all(isinstance(item, str) for item in gpt5_result):
135
+ return gpt5_result
136
+ # Format for WhatsApp if dict format
137
+ warehouse_info = []
138
+ for item in gpt5_result:
139
+ if isinstance(item, dict):
140
+ info = f"📦 {item.get('name', '')}"
141
+ if item.get('variant'):
142
+ info += f" ({item['variant']})"
143
+ if item.get('warehouses'):
144
+ info += f"\n📍 Mevcut: {', '.join(item['warehouses'])}"
145
+ if item.get('price'):
146
+ info += f"\n💰 {item['price']}"
147
+ warehouse_info.append(info)
148
+ else:
149
+ warehouse_info.append(str(item))
150
+ return warehouse_info if warehouse_info else None
151
  except Exception as e:
152
+ logger.error(f"GPT-5 warehouse search error: {e}")
153
+ # Continue to fallback search
154
 
155
+ # Fallback to original search
156
+ try:
157
+ import re
158
+ warehouse_url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php'
159
+ response = requests.get(warehouse_url, verify=False, timeout=15)
160
+
161
+ if response.status_code != 200:
162
+ return None
163
+
164
+ root = ET.fromstring(response.content)
165
+
166
+ # Turkish character normalization function
167
+ turkish_map = {'ı': 'i', 'ğ': 'g', 'ü': 'u', 'ş': 's', 'ö': 'o', 'ç': 'c', 'İ': 'i', 'I': 'i'}
168
+
169
+ def normalize_turkish(text):
170
+ import unicodedata
171
+ text = unicodedata.normalize('NFD', text)
172
+ text = ''.join(char for char in text if unicodedata.category(char) != 'Mn')
173
+ for tr_char, en_char in turkish_map.items():
174
+ text = text.replace(tr_char, en_char)
175
+ return text
176
+
177
+ # Normalize search product name
178
+ search_name = normalize_turkish(product_name.lower().strip())
179
+ search_name = search_name.replace('(2026)', '').replace('(2025)', '').replace(' gen 3', '').replace(' gen', '').strip()
180
+ search_words = search_name.split()
181
+
182
+ best_matches = []
183
+ exact_matches = []
184
+ variant_matches = []
185
+ candidates = []
186
+
187
+ # Separate size/color words from product words
188
+ size_color_words = ['s', 'm', 'l', 'xl', 'xs', 'small', 'medium', 'large',
189
+ 'turuncu', 'siyah', 'beyaz', 'mavi', 'kirmizi', 'yesil',
190
+ 'orange', 'black', 'white', 'blue', 'red', 'green']
191
+
192
+ variant_words = [word for word in search_words if word in size_color_words]
193
+ product_words = [word for word in search_words if word not in size_color_words]
194
+
195
+ # Check if this is a size/color specific query
196
+ is_size_color_query = len(variant_words) > 0 and len(search_words) <= 4
197
+
198
+ # İlk geçiş: Variant alanında beden/renk araması
199
+ if is_size_color_query:
200
+ for product in root.findall('Product'):
201
+ product_name_elem = product.find('ProductName')
202
+ variant_elem = product.find('ProductVariant')
203
+
204
+ if product_name_elem is not None and product_name_elem.text:
205
+ xml_product_name = product_name_elem.text.strip()
206
+ normalized_product_name = normalize_turkish(xml_product_name.lower())
207
+
208
+ # If there are product words, check if they match the product name
209
+ product_name_matches = True
210
+ if product_words:
211
+ product_name_matches = all(word in normalized_product_name for word in product_words)
212
+
213
+ # Only proceed if product name matches (or no product context)
214
+ if product_name_matches:
215
+ # Variant field check
216
+ if variant_elem is not None and variant_elem.text:
217
+ variant_text = normalize_turkish(variant_elem.text.lower().replace('-', ' '))
218
+
219
+ # Check if all variant words are in variant field
220
+ if all(word in variant_text for word in variant_words):
221
+ variant_matches.append((product, xml_product_name, variant_text))
222
+
223
+ if variant_matches:
224
+ candidates = variant_matches
225
+ else:
226
+ # Fallback to normal product name search
227
+ is_size_color_query = False
228
+
229
+ # İkinci geçiş: Normal ürün adı tam eşleşmeleri (variant match yoksa)
230
+ if not is_size_color_query or not candidates:
231
+ for product in root.findall('Product'):
232
+ product_name_elem = product.find('ProductName')
233
+ if product_name_elem is not None and product_name_elem.text:
234
+ xml_product_name = product_name_elem.text.strip()
235
+ normalized_xml = normalize_turkish(xml_product_name.lower())
236
+ normalized_xml = normalized_xml.replace('(2026)', '').replace('(2025)', '').replace(' gen 3', '').replace(' gen', '').strip()
237
+ xml_words = normalized_xml.split()
238
+
239
+ # Tam eşleşme kontrolü - ilk iki kelime tam aynı olmalı
240
+ if len(search_words) >= 2 and len(xml_words) >= 2:
241
+ search_key = f"{search_words[0]} {search_words[1]}"
242
+ xml_key = f"{xml_words[0]} {xml_words[1]}"
243
+
244
+ if search_key == xml_key:
245
+ exact_matches.append((product, xml_product_name, normalized_xml))
246
+
247
+ # Eğer variant match varsa onu kullan, yoksa exact matches kullan
248
+ if not candidates:
249
+ candidates = exact_matches if exact_matches else []
250
+
251
+ # Eğer hala bir match yoksa, fuzzy matching yap
252
+ if not candidates:
253
+ for product in root.findall('Product'):
254
+ product_name_elem = product.find('ProductName')
255
+ if product_name_elem is not None and product_name_elem.text:
256
+ xml_product_name = product_name_elem.text.strip()
257
+ normalized_xml = normalize_turkish(xml_product_name.lower())
258
+ normalized_xml = normalized_xml.replace('(2026)', '').replace('(2025)', '').replace(' gen 3', '').replace(' gen', '').strip()
259
+ xml_words = normalized_xml.split()
260
+
261
+ # Ortak kelime sayısını hesapla
262
+ common_words = set(search_words) & set(xml_words)
263
+
264
+ # En az 2 ortak kelime olmalı VE ilk kelime aynı olmalı (marka kontrolü)
265
+ if (len(common_words) >= 2 and
266
+ len(search_words) > 0 and len(xml_words) > 0 and
267
+ search_words[0] == xml_words[0]):
268
+ best_matches.append((product, xml_product_name, normalized_xml, len(common_words)))
269
+
270
+ # En çok ortak kelimeye sahip olanları seç
271
+ if best_matches:
272
+ max_common = max(match[3] for match in best_matches)
273
+ candidates = [(match[0], match[1], match[2]) for match in best_matches if match[3] == max_common]
274
+
275
+ # Stok bilgilerini topla ve tekrarları önle
276
+ warehouse_stock_map = {} # warehouse_name -> total_stock
277
+
278
+ for product, xml_name, _ in candidates:
279
+ # New B2B API structure: Warehouse elements are direct children of Product
280
+ for warehouse in product.findall('Warehouse'):
281
+ name_elem = warehouse.find('Name')
282
+ stock_elem = warehouse.find('Stock')
283
+
284
+ if name_elem is not None and stock_elem is not None:
285
+ warehouse_name = name_elem.text if name_elem.text else "Bilinmeyen"
286
+ try:
287
+ stock_count = int(stock_elem.text) if stock_elem.text else 0
288
+ if stock_count > 0:
289
+ # Aynı mağaza için stokları topla
290
+ if warehouse_name in warehouse_stock_map:
291
+ warehouse_stock_map[warehouse_name] += stock_count
292
+ else:
293
+ warehouse_stock_map[warehouse_name] = stock_count
294
+ except (ValueError, TypeError):
295
+ pass
296
+
297
+ if warehouse_stock_map:
298
+ # Mağaza stoklarını liste halinde döndür
299
+ all_warehouse_info = []
300
+ for warehouse_name, total_stock in warehouse_stock_map.items():
301
+ all_warehouse_info.append(f"{warehouse_name}: Stokta var")
302
+ return all_warehouse_info
303
+ else:
304
+ return ["Hiçbir mağazada stokta bulunmuyor"]
305
+
306
+ except Exception as e:
307
+ print(f"Mağaza stok bilgisi çekme hatası: {e}")
308
+ return None
309
 
310
  # Trek bisiklet ürünlerini çekme - DÜZELTİLMİŞ VERSİYON
311
  try:
 
1113
  except Exception as e:
1114
  logger.error(f"❌ BF Space: Improved search error: {e}")
1115
 
1116
+ # Fallback to warehouse search if improved search didn't work
1117
  if not product_found_improved:
1118
  # Check if message seems to be asking about products
1119
  product_keywords = ['fiyat', 'kaç', 'stok', 'var mı', 'mevcut', 'bisiklet', 'bike',
1120
+ 'trek', 'model', 'beden', 'renk', 'mağaza', 'nerede', 'hangi']
 
 
 
1121
 
1122
  # Common non-product responses
1123
  non_product_responses = ['süper', 'harika', 'güzel', 'teşekkür', 'tamam', 'olur',
 
1126
  is_product_query = False
1127
  lower_message = user_message.lower()
1128
 
 
 
 
1129
  # Check if it's likely a product query
1130
  if any(keyword in lower_message for keyword in product_keywords):
1131
  is_product_query = True
 
1132
  # Check if it's NOT a simple response
1133
  elif lower_message not in non_product_responses and len(lower_message.split()) > 1:
1134
  # Multi-word queries might be product searches
1135
  is_product_query = True
 
1136
  # Single short words are usually not products
1137
  elif len(lower_message.split()) == 1 and len(lower_message) < 6:
1138
  is_product_query = False
 
 
 
1139
 
1140
  if is_product_query:
1141
+ # Use GPT-5 warehouse search for product queries
1142
+ logger.info("📦 Using GPT-5 warehouse search")
1143
  warehouse_result = get_warehouse_stock(user_message)
1144
  if warehouse_result and warehouse_result != ['Ürün bulunamadı']:
1145
  warehouse_response = "\n".join(warehouse_result)
1146
  messages.append({
1147
  "role": "system",
1148
+ "content": f"MAĞAZA STOK BİLGİSİ:\n{warehouse_response}\n\nBu bilgileri kullanarak kullanıcıya yardımcı ol. Fiyat ve stok bilgilerini AYNEN kullan."
1149
  })
1150
+ logger.info(f"✅ Warehouse stock info added: {warehouse_response[:200]}...")
1151
  else:
1152
  logger.info(f"🚫 Skipping product search for: '{user_message}'")
1153