מחשבון תצורה בפיתוח 1C-Bitrix

מוצרים מורכבים עם אפשרויות רבות תמיד חשופים לשגיאות בהזמנות ולאובדן מכירות. אנחנו בונים מחשבוני קונפיגורציה על 1C-Bitrix שבודקים אוטומטית תאימות בין הרכיבים הנבחרים ומציגים את המחיר הסופי בזמן אמת. הצוות שלנו מספק את הקונפיגורטור במפתח מלא—ממודל הנתונים ועד ליישום—ומבטיח פעולה אמינה עם תמיכה מתמשכת.
השירותים שאנו מציעים
מציג 1 מתוך 1כל 1626 השירותים
מחשבון תצורה בפיתוח 1C-Bitrix
בינוני
~1-2 שבועות

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

שאלות נפוצות

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

אנחנו, צוות מפתחים מוסמכים עם 10 שנות ניסיון, מיישמים מחשבוני תצורה כאלה. הגישה שלנו מבטיחה פעולה אמינה גם עם 50+ אפשרויות. רלוונטי לסוכנויות רכב, יצרני רהיטים, אינטגרטורי IT וספקי ציוד תעשייתי. הזמינו פיתוח—נעריך את הפרויקט.

מה ההבדל מהצעות מסחריות סטנדרטיות?

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

כיצד מובנה מודל הנתונים?

אנו משתמשים ב-HL-block ConfiguratorComponents לאחסון אפשרויות:

שדה סוג תיאור
UF_PRODUCT_ID Int מזהה המוצר הבסיסי בקטלוג
UF_GROUP_CODE String קבוצת אפשרויות (מנוע, צבע, גלגלים)
UF_OPTION_CODE String קוד אפשרות
UF_OPTION_NAME String שם לתצוגה
UF_BASE_PRICE Float מחיר אפשרות
UF_PRICE_TYPE Enum קבוע / אחוז / דלתא
UF_INCOMPATIBLE String קודי אפשרויות לא תואמות (מופרדים בפסיקים)
UF_REQUIRED_WITH String אפשרויות נדרשות כאשר זו נבחרת

HL-block ConfiguratorPresets—תצורות מוכנות (בסיסית, סטנדרטית, לוקס):

שדה סוג תיאור
UF_PRODUCT_ID Int מוצר בסיסי
UF_PRESET_CODE String קוד תצורה מוכנה
UF_PRESET_NAME String שם
UF_OPTIONS_JSON Text JSON עם אפשרויות נבחרות
UF_DISCOUNT_PERCENT Float הנחה על התצורה המוכנה

מדוע גרף התלות קריטי לביצועים?

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

כיצד לנהל תלותיות בין אפשרויות?

הבעיה המרכזית של מחשבון התצורה היא סנכרון תלותיות. כאשר נבחרת אפשרות, עלינו: להסיר אפשרויות לא תואמות מקבוצות אחרות, להוסיף אוטומטית אפשרויות קשורות נדרשות, ולחשב מחדש את המחיר הכולל.

class ProductConfigurator {
  constructor(basePrice, components) {
    this.basePrice = basePrice;
    this.components = components;
    this.selected = {};
    this.graph = this.buildIncompatibilityGraph();
  }

  buildIncompatibilityGraph() {
    const graph = {};
    this.components.forEach(c => {
      if (c.uf_incompatible) {
        graph[c.uf_option_code] = c.uf_incompatible.split(',').map(s => s.trim());
      }
    });
    return graph;
  }

  selectOption(groupCode, optionCode) {
    const blocked = this.graph[optionCode] || [];
    Object.keys(this.selected).forEach(g => {
      if (blocked.includes(this.selected[g])) delete this.selected[g];
    });
    this.selected[groupCode] = optionCode;
    const c = this.components.find(
      x => x.uf_group_code === groupCode && x.uf_option_code === optionCode
    );
    if (c && c.uf_required_with) {
      c.uf_required_with.split(',').forEach(code => {
        const req = this.components.find(x => x.uf_option_code === code.trim());
        if (req) this.selected[req.uf_group_code] = req.uf_option_code;
      });
    }
    return this.calculate();
  }

  calculate() {
    let total = this.basePrice;
    const breakdown = [];
    Object.entries(this.selected).forEach(([group, code]) => {
      const c = this.components.find(
        x => x.uf_group_code === group && x.uf_option_code === code
      );
      if (!c) return;
      let price = 0;
      if (c.uf_price_type === 'fixed') price = c.uf_base_price;
      if (c.uf_price_type === 'percent') price = this.basePrice * c.uf_base_price / 100;
      if (c.uf_price_type === 'delta') price = c.uf_base_price;
      total += price;
      breakdown.push({ group, name: c.uf_option_name, price });
    });
    return { basePrice: this.basePrice, totalPrice: Math.round(total), breakdown };
  }
}

תצורות מוכנות כנקודת כניסה

רוב המשתמשים לא מתחילים להגדיר מאפס. תצורות מוכנות משמשות כנקודת התחלה עם אפשרות לכוונון עדין. תצורה מוכנה עם הנחה מעודדת בחירת חבילה מוכנה במקום הרכבה ידנית חלק אחר חלק. חיסכון בתקציב של עד 30%—בונוס מוחשי.

function applyPreset(configurator, preset) {
  const options = JSON.parse(preset.uf_options_json);
  configurator.selected = {};
  Object.entries(options).forEach(([group, code]) => {
    configurator.selected[group] = code;
  });
  const result = configurator.calculate();
  if (preset.uf_discount_percent > 0) {
    result.totalPrice = Math.round(result.totalPrice * (1 - preset.uf_discount_percent / 100));
    result.presetDiscount = preset.uf_discount_percent;
  }
  return result;
}

כיצד להוסיף את התצורה לעגלת Bitrix?

public function addToCart(int $baseProductId, array $selectedOptions): \Bitrix\Main\Result {
    $basket = \Bitrix\Sale\Basket::loadItemsForFUser(
        \Bitrix\Sale\Fuser::getId(),
        \Bitrix\Main\Context::getCurrent()->getSite()
    );
    $item = $basket->createItem('catalog', $baseProductId);
    $item->setFields([
        'QUANTITY' => 1,
        'PROPS' => [[
            'NAME' => 'Комплектация',
            'CODE' => 'CONFIGURATION',
            'VALUE' => json_encode($selectedOptions),
        ]]
    ]);
    foreach ($selectedOptions as $option) {
        if (!empty($option['product_id'])) {
            $optItem = $basket->createItem('catalog', $option['product_id']);
            $optItem->setFields([
                'QUANTITY' => 1,
                'PRICE' => $option['price'],
                'CUSTOM_PRICE' => 'Y',
            ]);
        }
    }
    return $basket->save();
}

שמירת תצורת משתמש

למשתמשים רשומים, אנו משתמשים ב-HL-block class ProductConfigurator { constructor(basePrice, components) { this.basePrice = basePrice; this.components = components; this.selected = {}; this.graph = this.buildIncompatibilityGraph(); } buildIncompatibilityGraph() { const graph = {}; this.components.forEach(c => { if (c.uf_incompatible) { graph[c.uf_option_code] = c.uf_incompatible.split(',').map(s => s.trim()); } }); return graph; } selectOption(groupCode, optionCode) { const blocked = this.graph[optionCode] || []; Object.keys(this.selected).forEach(g => { if (blocked.includes(this.selected[g])) delete this.selected[g]; }); this.selected[groupCode] = optionCode; const c = this.components.find( x => x.uf_group_code === groupCode && x.uf_option_code === optionCode ); if (c && c.uf_required_with) { c.uf_required_with.split(',').forEach(code => { const req = this.components.find(x => x.uf_option_code === code.trim()); if (req) this.selected[req.uf_group_code] = req.uf_option_code; }); } return this.calculate(); } calculate() { let total = this.basePrice; const breakdown = []; Object.entries(this.selected).forEach(([group, code]) => { const c = this.components.find( x => x.uf_group_code === group && x.uf_option_code === code ); if (!c) return; let price = 0; if (c.uf_price_type === 'fixed') price = c.uf_base_price; if (c.uf_price_type === 'percent') price = this.basePrice * c.uf_base_price / 100; if (c.uf_price_type === 'delta') price = c.uf_base_price; total += price; breakdown.push({ group, name: c.uf_option_name, price }); }); return { basePrice: this.basePrice, totalPrice: Math.round(total), breakdown }; } } :

$hash = md5($productId . json_encode($selectedOptions));
$existing = $SavedConfig::getList([
    'filter' => [
        '=UF_USER_ID' => $USER->GetID(),
        '=UF_HASH' => $hash
    ]
])->fetch();
if (!$existing) {
    $SavedConfig::add([
        'UF_USER_ID' => $USER->GetID(),
        'UF_PRODUCT_ID' => $productId,
        'UF_OPTIONS' => json_encode($selectedOptions),
        'UF_PRICE' => $totalPrice,
        'UF_HASH' => $hash,
    ]);
}

לאורחים, אנו משתמשים ב-sessionStorage או בעוגיות עם תוחלת חיים מוגבלת.

מדריך יישום שלב אחר שלב למחשבון תצורה

  1. צרו HL-blocks לאפשרויות ולתצורות מוכנות.
  2. מלאו נתונים—קבוצות, אפשרויות, מחיריהן ותלותיות.
  3. יישמו ווידג'ט JS על Bitrix Framework (או ממשק נפרד).
  4. שלבו עם העגלה באמצעות אירוע function applyPreset(configurator, preset) { const options = JSON.parse(preset.uf_options_json); configurator.selected = {}; Object.entries(options).forEach(([group, code]) => { configurator.selected[group] = code; }); const result = configurator.calculate(); if (preset.uf_discount_percent > 0) { result.totalPrice = Math.round(result.totalPrice * (1 - preset.uf_discount_percent / 100)); result.presetDiscount = preset.uf_discount_percent; } return result; } .
  5. הגדירו מטמון לפעולה מהירה עם אפשרויות רבות.

כיצד להבטיח מדרגיות של מחשבון התצורה?

עבור 100+ אפשרויות, אנו משתמשים במטמון מתויג. תוצאות חישוב ותאימות נשמרות במטמון לפי מפתח public function addToCart(int $baseProductId, array $selectedOptions): \Bitrix\Main\Result { $basket = \Bitrix\Sale\Basket::loadItemsForFUser( \Bitrix\Sale\Fuser::getId(), \Bitrix\Main\Context::getCurrent()->getSite() ); $item = $basket->createItem('catalog', $baseProductId); $item->setFields([ 'QUANTITY' => 1, 'PROPS' => [[ 'NAME' => 'Комплектация', 'CODE' => 'CONFIGURATION', 'VALUE' => json_encode($selectedOptions), ]] ]); foreach ($selectedOptions as $option) { if (!empty($option['product_id'])) { $optItem = $basket->createItem('catalog', $option['product_id']); $optItem->setFields([ 'QUANTITY' => 1, 'PRICE' => $option['price'], 'CUSTOM_PRICE' => 'Y', ]); } } return $basket->save(); } . כאשר אפשרויות משתנות, המטמון מתבטל באמצעות סוכן. שאילתות ל-HL-blocks ממותחמות לפי UF_PRODUCT_ID ו-UF_GROUP_CODE. זה מבטיח זמן תגובה מתחת ל-100 אלפיות השנייה גם בעומסי שיא.

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

  • עיצוב מודל הנתונים וגרף התלות.
  • פיתוח ווידג'ט החזית על Bitrix Framework.
  • שילוב עם העגלה וההזמנות.
  • שמירת תצורות למשתמשים רשומים ואורחים.
  • תיעוד API והתקנה.
  • הדרכת מנהלים לעבודה עם מחשבון התצורה.
  • תמיכה ל-30 יום לאחר השחרור.

לוחות זמנים לפיתוח

היקף תיאור לוח זמנים
בסיסי עד 5 קבוצות אפשרויות, ללא תלותיות, תצורות מוכנות 5–8 ימים
סטנדרטי 5–15 קבוצות, אי-תאימות, שמירת תצורה 2–3 שבועות
מורכב 15+ קבוצות, פריטים בעגלה, היסטוריית תצורה 4–8 שבועות
ייצור שילוב עם 1C למחירים ומלאי עדכניים 2–4 חודשים

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

צרו קשר לבדיקה מפורטת של הפרויקט שלכם. נעריך את המורכבות ונציע את הפתרון האופטימלי.