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

למה לחשב משלוח לפי משקל

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

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

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

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

יצירת צורת משלוח לפי משקל

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

שלב ראשון – כתיבת קוד בסיס

על מנת ליצור סוג משלוח חדש – משלוח לפי משקל, עלינו להרחיב את מחלקת הבסיס של משלוח בווקומרס – WC_Shipping_Method.
נתחיל בשלב הראשון, לכן ניצור קובץ חדש אשר יכיל את קוד הבסיס שלנו עבור משלוח לפי משקל.

<?php
/**
 * Class Weight_Based
 *
 * @package    dorzki\WooCommerce\Weight_Shipping\Shipping
 * @subpackage Weight_Based
 * @author     Dor Zuberi <webmaster@dorzki.co.il>
 * @link       https://www.dorzki.io
 * @version    1.0.0
 */

namespace dorzki\WooCommerce\Weight_Shipping\Shipping;

use WC_Shipping_Method;

// Block if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


/**
 * Class Weight_Based
 *
 * @package dorzki\WooCommerce\Weight_Shipping\Shipping
 */
class Weight_Based extends WC_Shipping_Method {

}

שלב שני – הגדרת פרטי משלוח

לאחר שיצנו את קוד הבסיס, עלינו להגדיר את פרטי סוג המשלוח החדש שאנו יוצרים לווקומרס.
ניצור פונקצייה חדשה, פונקציית בנאי (__construct) ובה נגדיר את פרטי המשלוח.

/**
 * Weight_Based constructor.
 *
 * @param int $instance_id shipping method instance number.
 */
public function __construct( $instance_id = 0 ) {

	$this->id          = 'weight_based';
	$this->instance_id = absint( $instance_id );

	$this->method_title       = __( 'Weight Based', 'dorzki-wc-weight-shipping' );
	$this->method_description = __( 'Calculate shipping based on order weight.', 'dorzki-wc-weight-shipping' );

	$this->supports = [ 'shipping-zones', 'instance-settings', 'instance-settings-modal' ];

	$this->register_shipping_fields();
	$this->title       = $this->get_option( 'title' );
	$this->tax_status  = $this->get_option( 'tax_status' );
	$this->base_cost   = (float) $this->get_option( 'base_cost' );
	$this->weight_unit = (float) $this->get_option( 'weight_unit' );
	$this->unit_cost   = (float) $this->get_option( 'unit_cost' );

	add_action( 'woocommerce_update_options_shipping_' . $this->id, [ $this, 'process_admin_options' ] );

}

בקוד הנ״ל אנו מגדירים לשיטת המשלוח שם ותיאור, וכוללים גם במה תומכת שיטת המשלוח שלנו.
שיטות משלוח יכולות לתמוך בעד 4 פרמטרים שונים:

  1. shipping-zones – שיטת המשלוח תומכת בחלוקה לאיזורי משלוח.
  2. instance-settings – שיטת המשלוח תומכת בשדות הגדרות פר מופע.
  3. settings – מופעל בברירת המחדל לצורך תאימות, האם שיטת המשלוח תומכת בהגדרות שלא תלויות במופעים שונים.
  4. instance-settings-modal – שיטת המשלוח תומכת במסך הגדרות שנפתח במודל.

כמובן שיש לשים את הפרמטרים שרלוונטיים לכם, בדוגמא שלנו הפעלנו את כולם.

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

לבסוף אנו מצמידים פונקציה שתרוץ ברגע שלוחצים על שמירה של ההגדרות, אותה נראה בהמשך.

שלב שלישי – רישום הגדרות משלוח

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

/**
 * Register shipping method settings.
 */
private function register_shipping_fields() {

	$this->instance_form_fields = [
		'title'       => [
			'title'       => __( 'Method Title', 'dorzki-wc-weight-shipping' ),
			'type'        => 'text',
			'description' => __( 'The shipping title, will be visible to the user.', 'dorzki-wc-weight-shipping' ),
			'default'     => __( 'Weight Based Shipping', 'dorzki-wc-weight-shipping' ),
			'desc_tip'    => true,
		],
		'tax_status'  => [
			'title'   => __( 'Taxes', 'dorzki-wc-weight-shipping' ),
			'type'    => 'select',
			'class'   => 'wc-enhanced-select',
			'default' => 'taxable',
			'options' => [
				'taxable' => __( 'Add Tax', 'dorzki-wc-weight-shipping' ),
				'none'    => __( 'Tax Free', 'dorzki-wc-weight-shipping' ),
			],
		],
		'base_cost'   => [
			'title'       => __( 'Base Cost', 'dorzki-wc-weight-shipping' ),
			'type'        => 'text',
			'description' => __( 'Base cost for shipping, leave empty or 0 for none.', 'dorzki-wc-weight-shipping' ),
			'default'     => 0,
			'desc_tip'    => true,
		],
		'weight_unit' => [
			'title'       => __( 'Weight Unit', 'dorzki-wc-weight-shipping' ),
			'type'        => 'text',
			'description' => __( 'Enter the weight unit in kg to base the calculation (for example: 0.1).', 'dorzki-wc-weight-shipping' ),
			'default'     => 0,
			'desc_tip'    => true,
		],
		'unit_cost'   => [
			'title'       => __( 'Unit Cost', 'dorzki-wc-weight-shipping' ),
			'type'        => 'text',
			'description' => __( 'Enter the price to multiply with "Weight Unit" for shipping calculation.', 'dorzki-wc-weight-shipping' ),
			'default'     => 0,
			'desc_tip'    => true,
		],
	];

}

בפונקציה זו אנו מעבירים למשתנה המחלקה instance_form_fields מערך אשר מכיל 5 שדות הגדרות.
שדות אלו יעזרו לנו לתת לבעל החנות את האפשרות להגדיר את הפרמטרים העיקיים של חישוב משלוח לפי משקל.

ההגדרות של החישוב שאנו מוסיפים הם השדות הבאים:

צילום מסך של מסך הגדרות משלוח לפי משקל בווקומרס

שלב רביעי – שמירת הגדרות

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

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

שלב חמישי – חישוב משלוח לפי משקל

בשלב זה עלינו לבצע את החישוב, אנונ משתמשים בפונקציה calculate_shippng המוגדרת במחלקת האב, אך משנים אותה לצרכים שלנו.
לכן אנחנו דורסים את הפונקציונליות של מחלקת האב ע״י שימוש בצורת חישוב מיוחדת שלנו.

/**
 * Calculate shipping based on order total weight.
 *
 * @param array $package cart contents.
 */
public function calculate_shipping( $package = [] ) {

	$method = [
		'id'      => $this->get_rate_id(),
		'label'   => $this->title,
		'cost'    => floatval( $this->base_cost ),
		'package' => $package,
	];

	$total_weight = 0;

	// Calculate weight.
	foreach ( $package['contents'] as $cart_product ) {

		$total_weight += floatval( $cart_product['data']->get_weight() * $cart_product['quantity'] );

	}

	$method['cost'] += floatval( ( $total_weight / $this->weight_unit ) * $this->unit_cost );

	$this->add_rate( $method );

}

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

כעת אנו מגדירים צורת משלוח חדשה אשר תוצג לגולש בעמוד עגלה וחנות:

  1. id – מזהה שנוצר אוטומית לצורך תאימות עם ווקומרס.
  2. label – שם המשלוח אשר יוצג, אנו משתמשים בשם אשר נשמר במסד בשלב הקודם.
  3. cost – עלות המשלוח, בתור התחלה אנחנו מגדירים את מחיר הבסיס שבעל החנות הגדיר.
  4. package – נתוני העגלה לפניהם בוצע החישוב, פשוט מעבירים את המערכת שקיבלנו.

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

( ( משקל כולל של המוצרים / יחידת משקל ) * מחיר ליחידה ) = עלות משלוח לפי משקל

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

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

שלב שישי – רישום סוג המשלוח

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

/**
 * Register new shipping types.
 *
 * @param array $shipping_types woocommerce registered shipping types.
 *
 * @return array
 */
public function dorzki_wc_weight_shipping_register_shipping_types( $shipping_types ) {

	require_once DZ_WC_WEIGHT_SHIP_PATH . "shipping/class-weight-based.php";

	$shipping_types['weight_based'] = 'dorzki\WooCommerce\Weight_Shipping\Shipping\Weight_Based';

	return $shipping_types;

}

add_filter( 'woocommerce_shipping_methods', 'dorzki_wc_weight_shipping_register_shipping_types' );

סיכום

חיוב משלוח לפי משקל בווקומרס הינו חלק מאוד משמעותי כאשר חברת השילוח של החנות מחייבת את החנות לפי משקל ההזמנה.

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

    כתיבת תגובה

    1. אשר

      יש לי שאלה בעניין חישוב המיסוי על המשלוח –
      בארץ יש מעמ על המשלוח גם.
      אם אני מגדיר את האופציה של taxable – אז אני צריך להכניס את עלות המשלוח לפני מעמ. זו עלות עם אגורות. בחישוב הכללי, הווקומרס נותן לי סיכום עם 10.01 או 9.99 (דוגמא למוצר שעלותו כולל משלוח ומעמ אמורה להיות סה"כ 10 שח).
      אם אני מגדיר non-taxable – אני מזין את עלויות המשלוח המלאות כולל מעמ ומקבל כשיסום מחיר מדויק (10 שח, לפי דוגמא זו), אבל אז הווקומרס לא מציג בחישוב המעמ את המעמ על המשלוח, אלא רק את המעמ על המוצר.
      רעיונות לפתרון?
      תודה

      הגב
      1. דור צוברי

        שלום אשר,
        ל-WooCommerce יש בעיה ידועה עם חישוב מע״מ, אם אני לא טועה הם מעגלים ל-2 ספרות, אז החישוב לא תמיד יוצא טוב.

        אני ממליץ לעשות שהזנת המחיר תהיה לפני מע״מ.

    2. רוב

      מאמר יפה, איזה שם צריך לקבצים ולאיפה לעלות אותם?

      הגב
      1. דור צוברי

        אהלן רוב 👋,
        אני ממליץ ליצור אותו כתוסף, אתה יכול להוריד מפה את הקוד המלא.

    אפשר להציע לך עוגיות? יש גם קפה! השימוש בקוקיז עוזר לשפר את הביקור שלך באתר. המשך גלישה אומר שהסכמת למדיניות הפרטיות שלי, וגם לקפה.

    שתפו