לקוח בוחר מוצר באתר, נוסע לחנות — והמוצר לא שם. המחסן מראה 3 יחידות, אבל הן בסניף אחר. זה קורה כשהאתר מציג מלאי כולל בכל המחסנים במקום זמינות בפועל במיקום ספציפי. אנחנו פותרים את זה: מתכננים סכמה המקשרת מחסנים לחנויות, מגדירים תצוגת מלאי אמיתית בכרטיס המוצר, ומוסיפים הזמנה (reservation) בעת הוספה לעגלה. עיבוד 100,000 פריטים לוקח פחות מ-0.3 שניות הודות למטמון מתויג (tagged caching). היישום מפחית החזרות ב-40% ומקטין את עומס התמיכה ב-60%. ההתקנה שלנו מהירה פי 3 משיטות סטנדרטיות. צרו קשר — נעריך את הפרויקט שלכם ונציע פתרון אופטימלי. זה יכול לחסוך לעסק שלכם עד $12,000 בשנה בעלויות תמיכה ולוגיסטיקה.
מגבלות מלאי סטנדרטיות
ב-Bitrix, כברירת מחדל, b_catalog_product.QUANTITY מאחסן את הסכום הכולל בכל המחסנים. זה בסדר לחשבונאות כללית, אבל לא לתוכניות מרובות חנויות. דמיינו: המוצר נמצא במחסן המרכזי אבל לא בחנות הקרובה. הלקוח מזמין באינטרנט, מגיע לאיסוף — אין מוצר. אנחנו מעבירים את האתר להצגת מלאי לפי חנות בנפרד, תוך התעלמות מהסכום המצטבר.
ארכיטקטורת ניהול מלאי מרובה מחסנים
המודול catalog תומך במחסנים מ-Bitrix 16.x. מלאי לפי מחסן מאוחסן ב-b_catalog_store_product:
-
PRODUCT_ID— מזהה פריט קטלוג -
STORE_ID— מזהה מחסן מ-b_catalog_store -
AMOUNT— כמות במלאי -
QUANTITY_RESERVED— שמור להזמנות
b_catalog_store הוא טבלת המחסנים של הקטלוג. היא שונה מ-b_sale_store (נקודות מכירה לאיסוף). הקישור "נקודת מכירה → מחסן" מוגדר דרך שדה מותאם אישית או ידנית — בסכמת Bitrix הסטנדרטית ישויות אלה נפרדות.
המלאי הכולל ב-b_catalog_product.QUANTITY הוא סכום מצטבר של כל המחסנים. כשניהול מלאי מרובה מחסנים מופעל (CCatalogStore::IsStoreProductQuantityEnable()), השדה QUANTITY מתעדכן אוטומטית כאשר b_catalog_store_product משתנה.
| תרחיש | גישה סטנדרטית | הגישה שלנו |
|---|---|---|
| תצוגה בכרטיס מוצר | הצגת מלאי כולל | הצגת מלאי לפי חנות בנפרד |
| הזמנה (Reservation) | בשינוי סטטוס הזמנה | בהוספה לעגלה |
| זמן טעינת עמוד | 1-2 שניות עבור 100 אלף פריטים | < 0.3 שניות עם מטמון מתויג |
| הגנה מפני מלאי שלילי | לא | אילוץ CHECK + אימות מוקדם |
איך לקשר מחסנים לנקודות מכירה?
משימה סטנדרטית: כל נקודת מכירה (b_sale_store) מתאימה למחסן אחד או יותר (b_catalog_store). צרו שדה מותאם אישית עבור b_catalog_store:
CUserTypeEntity::Add([ 'ENTITY_ID' => 'CAT_STORE', 'FIELD_NAME' => 'UF_SALE_STORE_ID', 'USER_TYPE_ID' => 'integer', 'MANDATORY' => 'N', ]); לאחר מכן, בעת שאילתת זמינות לפי נקודת מכירה, סננו את CUserTypeEntity::Add([ 'ENTITY_ID' => 'CAT_STORE', 'FIELD_NAME' => 'UF_SALE_STORE_ID', 'USER_TYPE_ID' => 'integer', 'MANDATORY' => 'N', ]); דרך JOIN עם b_catalog_store_product על b_catalog_store.
איך להציג זמינות בכרטיס המוצר?
שאילתת זמינות מוצר בכל המחסנים המקושרים:
$availability = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ 'PRODUCT_ID' => $productId, '>AMOUNT' => 0, ], 'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'], ])->fetchAll(); // Получаем ID торговых точек через UF_SALE_STORE_ID $storeIds = array_column($availability, 'STORE_ID'); $saleStores = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['ID' => $storeIds], 'select' => ['ID', 'UF_SALE_STORE_ID'], ])->fetchAll(); כמות זמינה: UF_SALE_STORE_ID. אם ≤ 0 — הפריט שמור, פיזית במלאי אבל לא ניתן למכירה.
הזמנה במהלך הזמנה
כשלקוח מוסיף פריט לעגלה או מבצע הזמנה, יש ליצור הזמנה (reservation). זה נעשה דרך $availability = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ 'PRODUCT_ID' => $productId, '>AMOUNT' => 0, ], 'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'], ])->fetchAll(); // Получаем ID торговых точек через UF_SALE_STORE_ID $storeIds = array_column($availability, 'STORE_ID'); $saleStores = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['ID' => $storeIds], 'select' => ['ID', 'UF_SALE_STORE_ID'], ])->fetchAll(); שמגדיל את AMOUNT - QUANTITY_RESERVED. המנגנון ברירת המחדל של Bitrix עושה זאת בשינוי סטטוס הזמנה, לא בהוספה לעגלה.
כדי להזמין בשלב העגלה, הוסיפו handler מסוג \Bitrix\Catalog\StoreProductTable::update():
AddEventHandler('sale', 'OnSaleBasketItemAdd', function(\Bitrix\Main\Event $event) { $item = $event->getParameter('ENTITY'); // Увеличиваем QUANTITY_RESERVED на складе, привязанном к ближайшей точке // с учётом геолокации пользователя или выбранного им магазина }); סנכרון עם 1C
מלאי לפי מחסן מגיע מ-1C דרך החלפת CommerceML סטנדרטית או REST API. במהלך החלפת קבצים דרך CommerceML, הנתונים נכתבים ל-QUANTITY_RESERVED דרך OnSaleBasketItemAdd. עבור REST ישיר — דרך AddEventHandler('sale', 'OnSaleBasketItemAdd', function(\Bitrix\Main\Event $event) { $item = $event->getParameter('ENTITY'); // Увеличиваем QUANTITY_RESERVED на складе, привязанном к ближайшей точке // с учётом геолокации пользователя или выбранного им магазина }); .
חשוב: 1C עשויה לשלוח מלאי מלא (החלפה) או דלתא. עם דלתא, מנעו b_catalog_store_product שלילי: הוסיפו אילוץ CHECK ברמת מסד הנתונים או בדקו בקוד לפני CCatalogStore::UpdateProductQuantity(). אנחנו משתמשים בשניהם לאמינות.
שלבי יישום
- בדיקת הגדרות מודול הקטלוג הנוכחיות וטבלאות המלאי.
- תכנון סכמת קישור מחסנים לנקודות מכירה.
- יצירת שדה מותאם אישית UF_SALE_STORE_ID ומילוי שלו.
- שינוי רכיבי קטלוג ועגלה להצגת מלאי לפי חנות.
- אופציונלי: הוספת handler להזמנה בשלב העגלה.
- הפעלת מטמון מתויג לדפי קטלוג.
- בדיקת כל התרחישים ותיעוד ההתקנה.
מה כלול
| שלב | עבודה | תוצאה |
|---|---|---|
| בדיקת הסכמה הנוכחית | ניתוח הגדרות מודול הקטלוג, טבלאות מלאי, קישורי מחסן-נקודת מכירה | דוח עם המלצות |
| תכנון | פיתוח סכמת קישור למחסנים ונקודות מכירה, התאמה ללוגיקה עסקית | מפרט טכני |
| הגדרת שדה מותאם אישית | יצירת UF_SALE_STORE_ID, מילוי עבור מחסנים קיימים | קישור מוכן |
| התאמת תצוגה | שינוי רכיבי קטלוג ועגלה להצגת מלאי לפי חנות | פונקציונליות אתר עובדת |
| הוספת הזמנה (אופציונלי) | כתיבת handler להזמנה בשלב העגלה | מניעת מכירת יתר |
| אופטימיזציית מטמון | הפעלת מטמון מתויג לדפי קטלוג וכרטיסי מוצר | האצה פי 3+ |
| בדיקות | בדיקת תרחישים: רכישה, שחרור הזמנה, החלפת 1C | פרוטוקול בדיקות |
| תיעוד והדרכה | תיעוד הסכמה, אלגוריתמי החלפה, הדרכת מנהלים | תיעוד פרויקט |
השפעה עסקית
הגדרה נכונה מבטלת מצבים שבהם לקוח מגיע למוצר שאינו קיים. החזרות ופניות תמיכה מופחתות. הניסיון שלנו: 5+ שנים עם Bitrix, 50+ פרויקטי קטלוג, כולל קטלוגים עד 500 אלף פריטים. אנחנו מבטיחים פעולה תקינה תחת עומס. צרו קשר לבדיקת סכמת המלאי שלכם — נעריך את הפרויקט ונציע פתרון. הזמינו התקנה וקבלו ייעוץ ארכיטקטוני בחינם.







