openbuildings/shipping

向 openbuildings/purchases 包件添加复杂的配送

安装量: 165,038

依赖项: 1

建议者: 1

安全性: 0

星标: 0

关注者: 11

分支: 2

开放问题: 3

类型:kohana-module


README

Build Status Scrutinizer Quality Score Code Coverage Latest Stable Version

使用方法

您想运输的采购项目必须实现 Shippable,例如这样

class Model_Product extends Jam_Model implements Sellable, Shippable {

	public static function initialize(Jam_Meta $meta)
	{
		$meta
			->associations(array(
				'shipping' => Jam::association('belongsto', array('inverse_of' => 'products')),
			))
			->fields(array(
				'id' => Jam::field('primary'),
				'name' => Jam::field('string'),
				'currency' => Jam::field('string'),
				'price' => Jam::field('price'),
			))
			->validator('type', 'price', 'quantity', array(
				'present' => TRUE
			));
	}

	// Implement Sellable
	public function price(Model_Purchase_Item $item)
	{
		return $this->price;
	}

	// Implement Sellable
	public function currency()
	{
		return $this->currency;
	}

	// Implement Shippable
	// Must return a ``Model_Shipping`` object holding all the data for the shipping
	public function shipping()
	{
		return $this->shipping;
	}

	// Implement Shippable
	// Must return a boolean whether or not the product ships can to that location
	public function ships_to(Model_Location $location)
	{
		return $this->shipping ? $this->shipping->ships_to($location) : FALSE;
	}
}

class Model_Purchase_Item_Product extends Kohana_Model_Purchase_Item_Product {

    public static function initialize(Jam_Meta $meta)
    {
        parent::initialize($meta);
        $meta
            ->behaviors(array(
                'shippable_purchase_item' => Jam::behavior('shippable_purchase_item'),
            ));
    }
}

class Model_Shipping extends Kohana_Model_Shipping {

	public static function initialize(Jam_Meta $meta)
	{
		parent::initialize($meta);

		$meta
			->associations(array(
				'products' => Jam::association('hasmany', [
                    'inverse_of' => 'shipping',
                ]),
			));
	}
}

此外,您还需要将可运输的采购项目添加到您的采购和品牌采购中

class Model_Brand_Purchase extends Kohana_Model_Brand_Purchase {

	public static function initialize(Jam_Meta $meta)
	{
		parent::initialize($meta);
		$meta
			->behaviors(array(
				'shippable_brand_purchase' => Jam::behavior('shippable_brand_purchase'),
			));
	}
}

class Model_Purchase extends Kohana_Model_Purchase {

	public static function initialize(Jam_Meta $meta)
	{
		parent::initialize($meta);
		$meta
			->behaviors(array(
				'shippable_purchase' => Jam::behavior('shippable_purchase'),
			));
	}
}

这些行为将为 brand_pruchase 添加 'shipping' 关联,并监听 update_items 事件以添加一个运输采购项目,并监听 filter_items 事件,添加更多筛选标志。

一旦您已将运输数据添加到您的产品中

$post = Jam::find('shipping_method', 'Post');
$europe = Jam::find('location', 'Europe');
$france = Jam::find('location', 'France');

$product->shipping = Jam::create('shipping', array(
	'currency' => 'GBP',
	'ships_from' => $france,
	'groups' => array(

		// Ships to all of Europe for 20 GBP
		array('method' => $post, 'location' => $europe, 'price' => 20),

		// Specifically for France - only 10 GBP
		array('method' => $post, 'location' => $france, 'price' => 10),
	)
));

您就可以开始选择哪些运输适用于每个采购项目。

$brand_purchase = Jam::find('brand_purchase', 1);

// If you want to set the informaction explicitly on which purchase_item what shipping_group to use
$brand_purchase->build('shipping', array(
	'items' => array(
		array(
			'purchase_item' => $brand_purchase->items[0],
			'shipping_group' => $brand_purchase->items[0]->reference->shipping()->groups[0],
		),
	)
));

// Or if you want ones selected automatically, based on a preffered shipping method and purchaser location
$post = Jam::find('shipping_method', 'Post');
$france = Jam::find('location', 'France');

$brand_purchase_shipping = $brand_purchase->build('shipping', array(
	'location' => $france,
));

$brand_purchase_shipping->build_items_from($brand_purchase->items, $post);

配置完成后,您现在可以在 purchase / brand_purchase 上调用 update_items() 方法,为 purchase_items 添加一个运输项目。

$brand_purchase->update_items();

echo $brand_purchase->items_count('shipping'); // should return 1

运输组和价格计算

每个运输组有几个属性会影响此物品运输的成本

  • 价格 - 这是运输 1 件物品的基础价格。
  • 额外项目价格 - 对于多个物品,第二、第三等物品需要此价格,而不是基础价格。
  • 折扣阈值 - 只要品牌采购超过此金额,则免费运输

以下是一些示例

如果一个物品的价格为 10,额外项目价格为 6,那么您将支付 10+6+6 的费用,用于 3 件相同的物品。

此外,项目将按运输方式、按 "ships_from" 位置进行分组,因此通过邮寄邮寄的 3 件不同物品将被分组。只有最昂贵的基准价格会被使用,所有其他的价格将使用额外项目价格。所以

Item 1: price 10, additional_item_price 6, quantity: 3
Item 2: price 12, additional_item_price 8, quantity: 2

Total Price will be (12 + 8) + 6 * 3

在搜索国家时,将使用最具体的国家进行计算,因此如果您正在为法国运输,并且您有一个针对欧洲的运输组和一个针对法国的运输组,则将使用第二个。

高级项目拆分

如果您想允许人们为不同的产品使用不同的方法,以下是您可以如何实现的方法

首先,找到所有可以 / 不可以运输到您国家的采购项目

$available = $brand_purchase->items(array('can_ship' => TRUE));
$not_shippable = $brand_purchase->items(array('can_ship' => FALSE));

如果您想更精确,您可以获取可用的项目,但按可用的运输方式分组,这样如果您的采购项目可以通过 邮寄快递 进行运输,而其他项目只能通过 邮寄 进行运输,它们将属于不同的组

$group_shipping_methods = $brand_purchase->group_shipping_methods()
foreach ($group_shipping_methods as $group)
{
	foreach ($group->group_shipping_items() as $items)
	{
		// Get all the purchase items, shippable to this location by this method.
		$items->purchase_items;

		// Calculate the price of these items, provide a total price to remove ones that are discounted based on it.
		$items->total_price();

		// Delivery
		$items->total_delivery_time();
	}
}

交货时间

此运输模块提供了广泛的计算交货时间的支持。

Model_Shipping_Group 有 "delivery_time" - 最小 - 最大工作日交付物品。Model_Shipping 有 process_time - 最小 - 最大工作日 "构建" 项。这两个都是 Jam_Ranges,共同表示特定位置的 total_delivery_time。

Model_Shipping 有此接口

$france = Jam::find('locaiton', 'France');

$shipping = $product->shipping();

// To get a Jam_Range object only for the delivery to that location
$shipping->delivery_time_for($france);

// To get a Jam_Range for delivery + processing for a specific country
$shipping->total_delivery_time_for($france);

可运输的采购行为还为 Model_Brand_Purchase 添加了一些用于处理交货时间计算的方法

// Get the Jam_Range object for the delivery time for the brand_purchase
$brand_purchase->total_delivery_time();

// Get the Jam_Range object if the dates that the purchase will arraive
// This is calculate based on the time the payment was made. If its not yet payed purchase, the current time is used.
$brand_purchase->delivery_time_dates();

运输地址

默认情况下,使用采购的账单地址作为运输地址。如果您想更改该地址,您必须更改 shipping_same_as_billing 字段并设置运输地址关联,该关联是相同的 Model_Address 对象。之后,所有计算都将使用 shipping_address 的国家,而不是账单地址。

$purchase = Jam::find('purchase', 1);

$purchase->shipping_same_as_billing = FALSE;
$purchase->build('shipping_address', array(
  'country' => Jam::find('country', 'United Kingdom'),
  'line1' => 'Street 1',
  // ...
));

## License

Copyright (c) 2012-2013, OpenBuildings Ltd. Developed by Ivan Kerin as part of [clippings.com](http://clippings.com)

Under BSD-3-Clause license, read LICENSE file.