מלאי אמיתי לפי נקודות איסוף: התאמה אישית של 1C-Bitrix

לקוח מתלונן: "בכרטיס המוצר כתוב '10 במלאי', אבל במציאות, בקניון המרכזי יש 5, ברחוב לנין יש 2, ובזאפאדני אין בכלל." הרכיב הסטנדרטי `bitrix:catalog.element` מסכם מלאי על פני כל המחסנים מבלי להפריד בין נקודות איסוף. הלקוח מגיע לחנות ריקה
השירותים שאנו מציעים
מציג 1 מתוך 1כל 1626 השירותים
מלאי אמיתי לפי נקודות איסוף: התאמה אישית של 1C-Bitrix
פשוט
~1 יום

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • image_website-b2b-advance_0.webp
    פיתוח אתר חברה B2B ADVANCE
    1458
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    פיתוח אתר לחברת FIXPER
    1019
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    פיתוח מבוסס Bitrix, Bitrix24, 1C לחברה פיתוח ווידג'ט להזמנת תורים אונליין למרכז רפואי
    761
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    פיתוח על בסיס 1C Enterprise עבור MIRSANBEL
    880
  • image_crm_dolbimby_434_0.webp
    פיתוח אתר על CRM Bitrix24 עבור DOLBIMBY
    804
  • image_crm_technotorgcomplex_453_0.webp
    פיתוח על בסיס Bitrix24 עבור חברת TECHNOTORGKOMPLEKS
    1162

לקוח מתלונן: "בכרטיס המוצר כתוב '10 במלאי', אבל במציאות, בקניון המרכזי יש 5, ברחוב לנין יש 2, ובזאפאדני אין בכלל." רכיב ה-bitrix:catalog.element הסטנדרטי מסכם את המלאי בכל המחסנים ללא הפרדה בין נקודות איסוף. הלקוח מגיע לחנות ריקה — המוניטין נפגע.

אנחנו פותרים את הבעיה הזו: אנו מציגים את הכמות האמיתית לכל חנות ומעדכנים את הנתונים בעת בחירת הצעת סחר ללא טעינה מחדש. באמצעות שאילתה ישירה לטבלת מלאי המחסנים עם פילטר לפי נקודות איסוף ושימוש ב-caching מתויג, העמוד נטען במהירות והנתונים תמיד עדכניים. אינטגרציה עם 1C דרך CommerceML מבטיחה עדכון מלאי אוטומטי בכל העלאה. זמן טעינת העמוד יורד מ-200ms ל-50ms בזכות caching מתויג, ודיוק הנתונים מובטח באמצעות סנכרון עם 1C.

למה הרכיב הסטנדרטי לא מתאים

bitrix:catalog.element מציג את סך המלאי משדה CATALOG_QUANTITY. כדי לפרק לפי מחסן, צריך לבצע שאילתה משלך לטבלת b_catalog_store_product. הנה מבנה שאילתה טיפוסי:

SELECT s.ID, s.TITLE, s.ADDRESS, COALESCE(sp.AMOUNT, 0) as AMOUNT, COALESCE(sp.QUANTITY_RESERVED, 0) as RESERVED, COALESCE(sp.AMOUNT, 0) - COALESCE(sp.QUANTITY_RESERVED, 0) as AVAILABLE FROM b_catalog_store s LEFT JOIN b_catalog_store_product sp ON sp.STORE_ID = s.ID AND sp.PRODUCT_ID = ? WHERE s.ACTIVE = 'Y' AND s.IS_SITE = 'Y' ORDER BY s.SORT ASC; 

הדגל SELECT s.ID, s.TITLE, s.ADDRESS, COALESCE(sp.AMOUNT, 0) as AMOUNT, COALESCE(sp.QUANTITY_RESERVED, 0) as RESERVED, COALESCE(sp.AMOUNT, 0) - COALESCE(sp.QUANTITY_RESERVED, 0) as AVAILABLE FROM b_catalog_store s LEFT JOIN b_catalog_store_product sp ON sp.STORE_ID = s.ID AND sp.PRODUCT_ID = ? WHERE s.ACTIVE = 'Y' AND s.IS_SITE = 'Y' ORDER BY s.SORT ASC; מבדיל בין נקודות איסוף למחסנים רגילים. הוא מוגדר בלוח הניהול: קטלוג → מחסנים → [עריכה].

איך להבדיל בין נקודת איסוף למחסן בביטריקס

בלוח הניהול, לכל מחסן יש שדה "נקודת איסוף" (IS_SITE). אם הדגל מופעל, במהלך החלפה עם 1C, המלאי למחסן זה ייספר בנפרד. בפועל, זה מאפשר ניהול תצוגה גמיש: לדוגמה, חנות מקוונת יכולה להציג רק חנויות איסוף, תוך אי-הכללת מחסנים סיטונאיים.

איך אנחנו עושים את זה

אנחנו מפתחים את הפונקציה IS_SITE = 'Y', שמביאה מלאי לכל נקודות האיסוף הפעילות בשאילתה אחת. אנו משתמשים ב-Bitrix ORM: getStoreAvailability() ו-\Bitrix\Catalog\StoreTable. קוד PHP:

function getStoreAvailability(int $productId): array { $result = []; $storesQuery = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['ACTIVE' => 'Y', 'IS_SITE' => 'Y'], 'select' => ['ID', 'TITLE', 'ADDRESS', 'GPS_N', 'GPS_S', 'SORT'], 'order' => ['SORT' => 'ASC'], ]); $stores = []; while ($store = $storesQuery->fetch()) { $stores[$store['ID']] = $store; } if (empty($stores)) { return []; } // Остатки одним запросом для всех складов $stockQuery = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ 'PRODUCT_ID' => $productId, 'STORE_ID' => array_keys($stores), ], 'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'], ]); $stocks = []; while ($stock = $stockQuery->fetch()) { $stocks[$stock['STORE_ID']] = $stock; } foreach ($stores as $storeId => $store) { $amount = (float)($stocks[$storeId]['AMOUNT'] ?? 0); $reserved = (float)($stocks[$storeId]['QUANTITY_RESERVED'] ?? 0); $available = max(0, $amount - $reserved); $result[] = [ 'ID' => $storeId, 'TITLE' => $store['TITLE'], 'ADDRESS' => $store['ADDRESS'], 'GPS_N' => $store['GPS_N'], 'GPS_S' => $store['GPS_S'], 'AMOUNT' => $amount, 'AVAILABLE' => $available, 'IN_STOCK' => $available > 0, ]; } return $result; } 

הפתרון שלנו משתמש ב-caching מתויג (tag \Bitrix\Catalog\StoreProductTable) — כשהמלאי משתנה, ה-cache מתבטל אוטומטית. זה מהיר פי 5 משאילתה סטנדרטית ללא cache. עבור 50 מחסנים, השאילתה מתבצעת בפחות מ-10 אלפיות השנייה.

מה אם יש יותר מ-50 חנויות?

למספר גדול של נקודות איסוף (50+), אנחנו מייעלים שאילתות. אנו מוסיפים אינדקסים על שדות function getStoreAvailability(int $productId): array { $result = []; $storesQuery = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['ACTIVE' => 'Y', 'IS_SITE' => 'Y'], 'select' => ['ID', 'TITLE', 'ADDRESS', 'GPS_N', 'GPS_S', 'SORT'], 'order' => ['SORT' => 'ASC'], ]); $stores = []; while ($store = $storesQuery->fetch()) { $stores[$store['ID']] = $store; } if (empty($stores)) { return []; } // Остатки одним запросом для всех складов $stockQuery = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ 'PRODUCT_ID' => $productId, 'STORE_ID' => array_keys($stores), ], 'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'], ]); $stocks = []; while ($stock = $stockQuery->fetch()) { $stocks[$stock['STORE_ID']] = $stock; } foreach ($stores as $storeId => $store) { $amount = (float)($stocks[$storeId]['AMOUNT'] ?? 0); $reserved = (float)($stocks[$storeId]['QUANTITY_RESERVED'] ?? 0); $available = max(0, $amount - $reserved); $result[] = [ 'ID' => $storeId, 'TITLE' => $store['TITLE'], 'ADDRESS' => $store['ADDRESS'], 'GPS_N' => $store['GPS_N'], 'GPS_S' => $store['GPS_S'], 'AMOUNT' => $amount, 'AVAILABLE' => $available, 'IN_STOCK' => $available > 0, ]; } return $result; } ו-catalog_store_product בטבלת STORE_ID ומשתמשים ב-caching עם זמן חיים של 5 דקות. זה מאפשר טיפול בעד 1000 מחסנים ללא פגיעה בביצועים. אם יש צורך ברעננות מיידית, אפשר לבטל את ה-caching — אבל עומס מסד הנתונים גדל. אנו ממליצים על פשרה: caching מתויג עם ביטול בעת החלפת 1C.

אינטגרציה לתבנית כרטיס המוצר

ב-PRODUCT_ID של רכיב b_catalog_store_product:

\Bitrix\Main\Loader::includeModule('catalog'); $storeAvailability = getStoreAvailability($arResult['ID']); $inStockCount = count(array_filter($storeAvailability, fn($s) => $s['IN_STOCK'])); ?> <div class="store-availability"> <?php if ($inStockCount > 0): ?> <div class="in-stock-summary"> В наличии в <?= $inStockCount ?> магазин<?= \Local\Helpers\Declension::get($inStockCount, ['е', 'е', 'ах']) ?> </div> <button class="toggle-stores" type="button">Показать все магазины</button> <ul class="store-list" style="display:none"> <?php foreach ($storeAvailability as $store): ?> <li class="store-item <?= $store['IN_STOCK'] ? 'in-stock' : 'out-of-stock' ?>"> <span class="store-name"><?= htmlspecialchars($store['TITLE']) ?></span> <span class="store-address"><?= htmlspecialchars($store['ADDRESS']) ?></span> <span class="store-qty"> <?= $store['IN_STOCK'] ? $store['AVAILABLE'] . ' шт.' : 'Нет в наличии' ?> </span> </li> <?php endforeach; ?> </ul> <?php else: ?> <div class="out-of-stock">Нет в наличии в магазинах</div> <?php endif; ?> </div> 

עדכון AJAX בעת בחירת הצעת סחר

למוצרים עם וריאציות (מידה, צבע), אנו מעדכנים מלאי ללא טעינת עמוד מחדש:

document.querySelectorAll('.offer-option').forEach(function(el) { el.addEventListener('change', function() { var offerId = this.value; fetch('/ajax/store-availability/?product_id=' + offerId) .then(r => r.json()) .then(data => updateStoreList(data.stores)); }); }); 

ה-endpoint template.php הוא קובץ PHP נפרד שמחזיר JSON עם התוצאה של bitrix:catalog.element.

מה כלול בעבודה

  • ניתוח סכמת המחסנים הנוכחית וסוגי ההצעות.
  • פיתוח פונקציית שליפת המלאי עם caching.
  • אינטגרציה של הבלוק לתבנית \Bitrix\Main\Loader::includeModule('catalog'); $storeAvailability = getStoreAvailability($arResult['ID']); $inStockCount = count(array_filter($storeAvailability, fn($s) => $s['IN_STOCK'])); ?> <div class="store-availability"> <?php if ($inStockCount > 0): ?> <div class="in-stock-summary"> В наличии в <?= $inStockCount ?> магазин<?= \Local\Helpers\Declension::get($inStockCount, ['е', 'е', 'ах']) ?> </div> <button class="toggle-stores" type="button">Показать все магазины</button> <ul class="store-list" style="display:none"> <?php foreach ($storeAvailability as $store): ?> <li class="store-item <?= $store['IN_STOCK'] ? 'in-stock' : 'out-of-stock' ?>"> <span class="store-name"><?= htmlspecialchars($store['TITLE']) ?></span> <span class="store-address"><?= htmlspecialchars($store['ADDRESS']) ?></span> <span class="store-qty"> <?= $store['IN_STOCK'] ? $store['AVAILABLE'] . ' шт.' : 'Нет в наличии' ?> </span> </li> <?php endforeach; ?> </ul> <?php else: ?> <div class="out-of-stock">Нет в наличии в магазинах</div> <?php endif; ?> </div> .
  • יצירת נתיב AJAX להצעות סחר.
  • בדיקות על נתונים אמיתיים (מ-2 עד 10 נקודות איסוף).
  • תיעוד להתאמות עתידיות ומסירת גישה.

השוואה: פתרון סטנדרטי מול שלנו

מאפיין document.querySelectorAll('.offer-option').forEach(function(el) { el.addEventListener('change', function() { var offerId = this.value; fetch('/ajax/store-availability/?product_id=' + offerId) .then(r => r.json()) .then(data => updateStoreList(data.stores)); }); }); סטנדרטי ההתאמה שלנו
תצוגה לפי חנות לא כן, עם כתובת ו-GPS
Caching לא מתויג, ביטול אוטומטי
עדכון בעת שינוי הצעה רק לאחר טעינה מחדש AJAX ללא טעינה מחדש
זמן טעינת עמוד ~200 אלפיות השנייה (ללא cache) ~50 אלפיות השנייה (עם cache)

בניגוד לפתרון הסטנדרטי, ההתאמה שלנו לא רק מציגה מלאי לפי חנות אלא גם מאפשרת ללקוח לראות את הכתובת וקואורדינטות GPS, נוחות לתכנון מסלול.

שלבים ולוח זמנים

שלב משימות זמן
ניתוח בדיקת מבנה המחסנים, סוגי הצעות, תבנית נוכחית 1-2 שעות
פיתוח פונקציית getStoreAvailability, caching, endpoint AJAX 3-4 שעות
אינטגרציה סמני בלוק בתבנית catalog.element, בדיקות 2-3 שעות
בדיקות בדיקה על נתונים אמיתיים, תרחישים עם מלאי 1-2 שעות
תיעוד תיאור התאמות, מסירת גישה 0.5-1 שעה

סה"כ: 8 עד 12 שעות בהתאם למורכבות הקטלוג ומספר המחסנים. צרו קשר — נעריך את הפרויקט שלכם תוך יום עסקים אחד.

מומחי 1C-Bitrix מוסמכים עם ניסיון של למעלה מ-5 שנים מבטיחים אינטגרציה ללא שגיאות ותמיכה מלאה. פנו אלינו לקבלת הערכת עלות. הזמינו את ההתקנה, והחנות המקוונת שלכם תציג מלאי אמיתי לכל נקודת איסוף.