Update to new B2B API with improved structure
Browse files- Updated URL to bizimhesap-warehouse-xml-b2b-api.php
- Changed XML parsing for new structure (ProductVariant instead of Variant)
- Updated warehouse parsing (direct Warehouse children instead of nested)
- Improved context-aware search for better variant matching
- New API has actual stock data with proper structure
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
- app.py +53 -26
- test_new_api.py +29 -0
app.py
CHANGED
@@ -69,10 +69,18 @@ def get_warehouse_stock(product_name):
|
|
69 |
search_name = search_name.replace('(2026)', '').replace('(2025)', '').replace(' gen 3', '').replace(' gen', '').strip()
|
70 |
search_words = search_name.split()
|
71 |
|
72 |
-
#
|
73 |
candidates = []
|
74 |
product_count = 0
|
75 |
-
max_products =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
for product in root.findall('Product'):
|
78 |
if product_count >= max_products:
|
@@ -80,37 +88,56 @@ def get_warehouse_stock(product_name):
|
|
80 |
product_count += 1
|
81 |
|
82 |
product_name_elem = product.find('ProductName')
|
|
|
|
|
83 |
if product_name_elem is not None and product_name_elem.text:
|
84 |
xml_product_name = product_name_elem.text.strip()
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
-
#
|
88 |
-
if
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
91 |
break
|
92 |
|
93 |
-
# Collect stock info
|
94 |
warehouse_stock_map = {}
|
95 |
|
96 |
-
for product, xml_name in candidates:
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
if
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
pass
|
114 |
|
115 |
# Cancel alarm
|
116 |
signal.alarm(0)
|
|
|
69 |
search_name = search_name.replace('(2026)', '').replace('(2025)', '').replace(' gen 3', '').replace(' gen', '').strip()
|
70 |
search_words = search_name.split()
|
71 |
|
72 |
+
# Search using new B2B API structure
|
73 |
candidates = []
|
74 |
product_count = 0
|
75 |
+
max_products = 100 # Increase limit for new API
|
76 |
+
|
77 |
+
# Separate size/color words from product words for context-aware search
|
78 |
+
size_color_words = ['s', 'm', 'l', 'xl', 'xs', 'small', 'medium', 'large',
|
79 |
+
'turuncu', 'siyah', 'beyaz', 'mavi', 'kirmizi', 'yesil',
|
80 |
+
'orange', 'black', 'white', 'blue', 'red', 'green']
|
81 |
+
|
82 |
+
variant_words = [word for word in search_words if word in size_color_words]
|
83 |
+
product_words = [word for word in search_words if word not in size_color_words]
|
84 |
|
85 |
for product in root.findall('Product'):
|
86 |
if product_count >= max_products:
|
|
|
88 |
product_count += 1
|
89 |
|
90 |
product_name_elem = product.find('ProductName')
|
91 |
+
variant_elem = product.find('ProductVariant')
|
92 |
+
|
93 |
if product_name_elem is not None and product_name_elem.text:
|
94 |
xml_product_name = product_name_elem.text.strip()
|
95 |
+
normalized_name = normalize_turkish(xml_product_name.lower())
|
96 |
+
|
97 |
+
variant_text = ""
|
98 |
+
if variant_elem is not None and variant_elem.text:
|
99 |
+
variant_text = normalize_turkish(variant_elem.text.strip().lower())
|
100 |
+
|
101 |
+
# Context-aware matching
|
102 |
+
name_match = False
|
103 |
+
variant_match = False
|
104 |
+
|
105 |
+
# Check product name match
|
106 |
+
if product_words:
|
107 |
+
name_match = all(word in normalized_name for word in product_words)
|
108 |
+
else:
|
109 |
+
name_match = any(word in normalized_name for word in search_words if len(word) > 2)
|
110 |
|
111 |
+
# Check variant match
|
112 |
+
if variant_words and variant_text:
|
113 |
+
variant_match = all(word in variant_text for word in variant_words)
|
114 |
+
|
115 |
+
# Include if name matches and (no variant search OR variant matches)
|
116 |
+
if name_match and (not variant_words or variant_match):
|
117 |
+
candidates.append((product, xml_product_name, variant_text))
|
118 |
+
if len(candidates) >= 10: # Limit candidates
|
119 |
break
|
120 |
|
121 |
+
# Collect stock info from new structure
|
122 |
warehouse_stock_map = {}
|
123 |
|
124 |
+
for product, xml_name, variant in candidates:
|
125 |
+
# New structure: Warehouse elements are direct children of Product
|
126 |
+
for warehouse in product.findall('Warehouse'):
|
127 |
+
name_elem = warehouse.find('Name')
|
128 |
+
stock_elem = warehouse.find('Stock')
|
129 |
+
|
130 |
+
if name_elem is not None and stock_elem is not None:
|
131 |
+
warehouse_name = name_elem.text if name_elem.text else "Bilinmeyen"
|
132 |
+
try:
|
133 |
+
stock_count = int(stock_elem.text) if stock_elem.text else 0
|
134 |
+
if stock_count > 0:
|
135 |
+
if warehouse_name in warehouse_stock_map:
|
136 |
+
warehouse_stock_map[warehouse_name] += stock_count
|
137 |
+
else:
|
138 |
+
warehouse_stock_map[warehouse_name] = stock_count
|
139 |
+
except (ValueError, TypeError):
|
140 |
+
pass
|
|
|
141 |
|
142 |
# Cancel alarm
|
143 |
signal.alarm(0)
|
test_new_api.py
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
# Test new B2B API with updated function
|
3 |
+
|
4 |
+
import sys
|
5 |
+
import os
|
6 |
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
7 |
+
|
8 |
+
from app import get_warehouse_stock
|
9 |
+
|
10 |
+
if __name__ == "__main__":
|
11 |
+
test_cases = [
|
12 |
+
"M Turuncu", # Should find M Turuncu variants
|
13 |
+
"Marlin M Turuncu", # Should find Marlin M Turuncu variants
|
14 |
+
"L Turuncu", # Should find L Turuncu variants
|
15 |
+
]
|
16 |
+
|
17 |
+
for test_case in test_cases:
|
18 |
+
print(f"\n=== Testing: {test_case} ===")
|
19 |
+
try:
|
20 |
+
result = get_warehouse_stock(test_case)
|
21 |
+
if result:
|
22 |
+
print("Sonuç:")
|
23 |
+
for item in result:
|
24 |
+
print(f" • {item}")
|
25 |
+
else:
|
26 |
+
print("Sonuç bulunamadı")
|
27 |
+
except Exception as e:
|
28 |
+
print(f"Hata: {e}")
|
29 |
+
print("-" * 50)
|