diff --git a/assets/js/blocks/checkout-pickup-location-select/slotfills/pickup-location-select.js b/assets/js/blocks/checkout-pickup-location-select/slotfills/pickup-location-select.js
index 8629dec3..9a180e2c 100644
--- a/assets/js/blocks/checkout-pickup-location-select/slotfills/pickup-location-select.js
+++ b/assets/js/blocks/checkout-pickup-location-select/slotfills/pickup-location-select.js
@@ -2,14 +2,8 @@ import { ExperimentalOrderShippingPackages } from '@woocommerce/blocks-checkout'
import { registerPlugin } from '@wordpress/plugins';
import { useEffect, useCallback, useState, useMemo } from "@wordpress/element";
import { useSelect, useDispatch, select, dispatch } from '@wordpress/data';
-import triggerFetch from '@wordpress/api-fetch';
-import { extensionCartUpdate } from '@woocommerce/blocks-checkout';
-import classnames from 'classnames';
-import { getSetting } from '@woocommerce/settings';
import { __, _x, sprintf } from '@wordpress/i18n';
-import { SVG } from '@wordpress/components';
-import _ from 'lodash';
-import { CART_STORE_KEY, CHECKOUT_STORE_KEY, PAYMENT_STORE_KEY, VALIDATION_STORE_KEY } from '@woocommerce/block-data';
+import { CART_STORE_KEY, CHECKOUT_STORE_KEY } from '@woocommerce/block-data';
import {
ValidatedTextInput,
@@ -17,15 +11,17 @@ import {
} from '@woocommerce/blocks-checkout';
import { decodeEntities } from '@wordpress/html-entities';
-import { useDebouncedCallback, useDebounce } from 'use-debounce';
-import { getSelectedShippingProviders, Combobox, hasShippingProvider } from '@woocommerceGzdShipments/blocks-checkout';
+import { getSelectedShippingProviders, Combobox, hasShippingProvider, getCheckoutData, hasPickupLocation } from '@woocommerceGzdShipments/blocks-checkout';
+
+import './style.scss';
const PickupLocationSelect = ({
extensions,
cart,
components
}) => {
- const [ needsCustomerNumber, setNeedsCustomerNumber ] = useState( false );
+ const [ supportsCustomerNumber, setSupportsCustomerNumber ] = useState( false );
+ const [ customerNumberIsMandatory, setCustomerNumberIsMandatory ] = useState( false );
const {
shippingRates,
@@ -54,16 +50,7 @@ const PickupLocationSelect = ({
};
} );
- const { checkoutOptions } = useSelect( ( select ) => {
- const store = select( CHECKOUT_STORE_KEY );
-
- const extensionsData = store.getExtensionData();
- const shipmentsData = extensionsData.hasOwnProperty( 'woocommerce-gzd-shipments' ) ? extensionsData['woocommerce-gzd-shipments'] : { 'pickup_location': '', 'pickup_location_customer_number': '' };
-
- return {
- checkoutOptions: shipmentsData
- };
- } );
+ const checkoutOptions = getCheckoutData();
const availableLocations = useMemo(
() =>
@@ -113,7 +100,8 @@ const PickupLocationSelect = ({
const currentLocation = getLocationByCode( checkoutOptions.pickup_location );
if ( currentLocation ) {
- setNeedsCustomerNumber( () => { return currentLocation.needs_customer_number } );
+ setSupportsCustomerNumber( () => { return currentLocation.supports_customer_number } );
+ setCustomerNumberIsMandatory( () => { return currentLocation.customer_number_is_mandatory } );
const newShippingAddress = { ...shippingAddress };
@@ -156,8 +144,6 @@ const PickupLocationSelect = ({
pickupLocationDeliveryAvailable
] );
- console.log(checkoutOptions);
-
if ( needsShipping && pickupLocationDeliveryAvailable ) {
return (
@@ -167,6 +153,7 @@ const PickupLocationSelect = ({
- { needsCustomerNumber && (
+ { supportsCustomerNumber && (
{
setOption( 'pickup_location_customer_number', newValue );
diff --git a/assets/js/blocks/checkout-pickup-location-select/slotfills/style.scss b/assets/js/blocks/checkout-pickup-location-select/slotfills/style.scss
index de880d8e..90f91d75 100644
--- a/assets/js/blocks/checkout-pickup-location-select/slotfills/style.scss
+++ b/assets/js/blocks/checkout-pickup-location-select/slotfills/style.scss
@@ -1,123 +1,5 @@
-.wc-gzd-checkout-dhl {
- .wc-gzd-checkout-dhl-title {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
+.wc-gzd-shipments-pickup-location-delivery {
+ h4 {
font-size: 1em;
-
- .dhl-icon {
- width: 130px;
- height: auto;
- margin-left: auto;
- }
- }
-
- .wc-block-components-radio-control-accordion-option {
- position: relative;
-
- .wc-block-components-radio-control__option-layout {
- font-size: .875em;
- }
-
- .wc-block-components-radio-control-accordion-content {
- font-size: .875em;
- }
-
- .wc-block-components-radio-control__option {
- border-bottom: none;
- padding-left: 56px;
- padding-right: 16px;
- margin: 0;
- padding-bottom: 1em;
- padding-top: 1em;
-
- &::after {
- border-style: solid;
- border-width: 1px 1px 0;
- bottom: 0;
- content: "";
- display: block;
- left: 0;
- opacity: .3;
- pointer-events: none;
- position: absolute;
- right: 0;
- top: 0;
- }
-
- .wc-block-components-radio-control__input {
- left: 16px;
- }
-
- &::after {
- border-width: 0;
- }
- }
-
- &::after {
- border-style: solid;
- border-width: 1px 1px 0;
- bottom: 0;
- content: "";
- display: block;
- left: 0;
- opacity: .3;
- pointer-events: none;
- position: absolute;
- right: 0;
- top: 0;
- }
-
- &:last-child {
- &::after {
- border-width: 1px;
- }
- }
- }
-
- .wc-gzd-dhl-preferred-day-select {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- margin: 0;
- padding: 0;
-
- .wc-gzd-dhl-preferred-day {
- color: inherit;
- flex-basis: 10%;
- flex-grow: 1;
- text-align: center;
- padding: 10px 0 0;
- margin: 0 8px 8px 0;
- background-color: #e3e3e3;
- border: none;
-
- &:last-child {
- margin-right: 0;
- }
-
- .inner {
- position: relative;
- display: flex;
- flex-direction: column;
- flex-wrap: wrap;
- padding: 5px 10px;
- font-size: 1em;
- background-color: #eef4f2;
- cursor: pointer;
- margin: 0;
- line-height: 1.8em;
-
- .day {
- font-size: 1.4em;
- }
- }
-
- &.active {
- .inner {
- background-color: #FFCC00;
- }
- }
- }
}
}
\ No newline at end of file
diff --git a/assets/js/packages/checkout/utils/index.js b/assets/js/packages/checkout/utils/index.js
index 2739cbad..7fe18d96 100644
--- a/assets/js/packages/checkout/utils/index.js
+++ b/assets/js/packages/checkout/utils/index.js
@@ -1,6 +1,19 @@
+import { CHECKOUT_STORE_KEY, CART_STORE_KEY } from '@woocommerce/block-data';
+import { useSelect, useDispatch, select, dispatch } from '@wordpress/data';
+import {useCallback} from "@wordpress/element";
+
export const getSelectedShippingProviders = (
- shippingRates
+ shippingRates = null
) => {
+ if ( null === shippingRates ) {
+ shippingRates = useSelect( ( select ) => {
+ const isEditor = !! select( 'core/editor' );
+ const store = select( CART_STORE_KEY );
+
+ return isEditor ? [] : store.getShippingRates();
+ } );
+ }
+
return Object.fromEntries( shippingRates.map( ( { package_id: packageId, shipping_rates: packageRates } ) => {
const meta_data = packageRates.find( ( rate ) => rate.selected )?.meta_data || [];
let provider = '';
@@ -18,6 +31,29 @@ export const getSelectedShippingProviders = (
} ) );
};
-export const hasShippingProvider = ( shippingProviders, shippingProvider ) => {
+export const hasShippingProvider = ( shippingProvider, shippingProviders = null ) => {
+ shippingProviders = null === shippingProviders ? getSelectedShippingProviders() : shippingProviders;
+
return Object.values( shippingProviders ).includes( shippingProvider );
+};
+
+export const hasPickupLocation = () => {
+ const checkoutData = getCheckoutData();
+
+ return !!checkoutData.pickup_location;
+};
+
+export const getCheckoutData = () => {
+ const { checkoutOptions } = useSelect( ( select ) => {
+ const store = select( CHECKOUT_STORE_KEY );
+
+ const extensionsData = store.getExtensionData();
+ const shipmentsData = extensionsData.hasOwnProperty( 'woocommerce-gzd-shipments' ) ? extensionsData['woocommerce-gzd-shipments'] : { 'pickup_location': '', 'pickup_location_customer_number': '' };
+
+ return {
+ checkoutOptions: shipmentsData
+ };
+ } );
+
+ return checkoutOptions;
};
\ No newline at end of file
diff --git a/src/Admin/Admin.php b/src/Admin/Admin.php
index 2d25519f..24452ff9 100644
--- a/src/Admin/Admin.php
+++ b/src/Admin/Admin.php
@@ -100,6 +100,36 @@ function() {
add_action( 'woocommerce_admin_field_dimensions', array( __CLASS__, 'register_dimensions_field' ), 30 );
add_filter( 'woocommerce_admin_settings_sanitize_option', array( __CLASS__, 'sanitize_dimensions_field' ), 10, 3 );
+
+ add_filter( 'woocommerce_admin_shipping_fields', array( __CLASS__, 'register_pickup_location_admin_fields' ), 10, 3 );
+ }
+
+ public static function register_pickup_location_admin_fields( $fields, $order = null, $context = 'edit' ) {
+ if ( ! $order instanceof \WC_Order ) {
+ return $fields;
+ }
+
+ $shipment_order = wc_gzd_get_shipment_order( $order );
+
+ if ( $shipment_order->supports_pickup_location() ) {
+ $fields['pickup_location_code'] = array(
+ 'label' => _x( 'Pickup location', 'shipments', 'woocommerce-germanized-shipments' ),
+ 'type' => 'text',
+ 'id' => '_pickup_location_code',
+ 'show' => false,
+ 'value' => $shipment_order->get_pickup_location_code(),
+ );
+
+ $fields['pickup_location_customer_number'] = array(
+ 'label' => _x( 'Pickup customer number', 'shipments', 'woocommerce-germanized-shipments' ),
+ 'show' => false,
+ 'id' => '_pickup_location_customer_number',
+ 'type' => 'text',
+ 'value' => $shipment_order->get_pickup_location_customer_number(),
+ );
+ }
+
+ return $fields;
}
public static function sanitize_toggle_field( $value, $option, $raw_value ) {
diff --git a/src/Blocks/Checkout.php b/src/Blocks/Checkout.php
index 2add381c..bc380573 100644
--- a/src/Blocks/Checkout.php
+++ b/src/Blocks/Checkout.php
@@ -5,6 +5,7 @@
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
use Automattic\WooCommerce\StoreApi\Schemas\V1\CartSchema;
use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
+use Automattic\WooCommerce\StoreApi\Utilities\CartController;
use Vendidero\Germanized\Shipments\Package;
final class Checkout {
@@ -47,6 +48,8 @@ private function get_checkout_data_from_request( $request ) {
)
);
+ $data['pickup_location_customer_number'] = trim( preg_replace( '/\s+/', '', $data['pickup_location_customer_number'] ) );
+
return $data;
}
@@ -62,7 +65,8 @@ private function validate_checkout_data( $order, $request ) {
if ( $this->has_checkout_data( 'pickup_location', $request ) ) {
$pickup_location_code = $gzd_data['pickup_location'];
$pickup_location_customer_number = $gzd_data['pickup_location_customer_number'];
- $needs_customer_number = false;
+ $supports_customer_number = false;
+ $customer_number_is_mandatory = false;
$is_valid = false;
$pickup_location = false;
$address_data = array(
@@ -74,32 +78,32 @@ private function validate_checkout_data( $order, $request ) {
if ( $provider = wc_gzd_get_order_shipping_provider( $order ) ) {
if ( is_a( $provider, 'Vendidero\Germanized\Shipments\Interfaces\ShippingProviderAuto' ) ) {
- $pickup_location = $provider->get_pickup_location_by_code( $pickup_location_code, $address_data );
- $is_valid = $provider->is_valid_pickup_location( $pickup_location_code, $address_data );
- $needs_customer_number = $provider->pickup_location_needs_customer_number( $pickup_location_code, $address_data );
+ $pickup_location = $provider->get_pickup_location_by_code( $pickup_location_code, $address_data );
+ $is_valid = $provider->is_valid_pickup_location( $pickup_location_code, $address_data );
+ $supports_customer_number = $pickup_location ? $pickup_location->supports_customer_number() : false;
+ $customer_number_is_mandatory = $pickup_location ? $pickup_location->customer_number_is_mandatory() : false;
- if ( $is_valid && $needs_customer_number ) {
- if ( ! $provider->is_valid_pickup_location_customer_number( $pickup_location_customer_number ) ) {
+ if ( $is_valid && $customer_number_is_mandatory ) {
+ if ( ! $pickup_location ) {
throw new \Automattic\WooCommerce\StoreApi\Exceptions\RouteException( 'pickup_location_customer_number_invalid', _x( 'Sorry, your pickup location customer number is invalid.', 'shipments', 'woocommerce-germanized-shipments' ), 400 );
+ } elseif ( ! $validation = $pickup_location->customer_number_is_valid( $pickup_location_customer_number ) ) {
+ if ( is_a( $validation, 'WP_Error' ) ) {
+ throw new \Automattic\WooCommerce\StoreApi\Exceptions\RouteException( 'pickup_location_customer_number_invalid', $validation->get_error_message(), 400 );
+ } else {
+ throw new \Automattic\WooCommerce\StoreApi\Exceptions\RouteException( 'pickup_location_customer_number_invalid', _x( 'Sorry, your pickup location customer number is invalid.', 'shipments', 'woocommerce-germanized-shipments' ), 400 );
+ }
}
}
}
}
if ( $is_valid && $pickup_location ) {
- $pickup_location_code = $pickup_location['code'];
-
- foreach ( $pickup_location['address_replacements'] as $address_field => $replacement ) {
- $setter = "set_shipping_{$address_field}";
-
- if ( is_callable( array( $order, $setter ) ) ) {
- $order->{ $setter }( $replacement );
- }
- }
+ $pickup_location_code = $pickup_location->get_code();
+ $pickup_location->replace_address( $order );
$order->update_meta_data( '_pickup_location_code', $pickup_location_code );
- if ( $needs_customer_number ) {
+ if ( $supports_customer_number ) {
$order->update_meta_data( '_pickup_location_customer_number', $pickup_location_customer_number );
}
@@ -110,16 +114,9 @@ private function validate_checkout_data( $order, $request ) {
$wc_customer = new \WC_Customer( $order->get_customer_id() );
$wc_customer->update_meta_data( 'pickup_location_code', $pickup_location_code );
+ $pickup_location->replace_address( $wc_customer );
- foreach ( $pickup_location['address_replacements'] as $address_field => $replacement ) {
- $setter = "set_shipping_{$address_field}";
-
- if ( is_callable( array( $wc_customer, $setter ) ) ) {
- $wc_customer->{ $setter }( $replacement );
- }
- }
-
- if ( $needs_customer_number ) {
+ if ( $supports_customer_number ) {
$wc_customer->update_meta_data( 'pickup_location_customer_number', $pickup_location_customer_number );
}
@@ -128,16 +125,9 @@ private function validate_checkout_data( $order, $request ) {
$customer = wc()->customer;
$customer->update_meta_data( 'pickup_location_code', $pickup_location_code );
+ $pickup_location->replace_address( $customer );
- foreach ( $pickup_location['address_replacements'] as $address_field => $replacement ) {
- $setter = "set_shipping_{$address_field}";
-
- if ( is_callable( array( $customer, $setter ) ) ) {
- $customer->{ $setter }( $replacement );
- }
- }
-
- if ( $needs_customer_number ) {
+ if ( $supports_customer_number ) {
$customer->update_meta_data( 'pickup_location_customer_number', $pickup_location_customer_number );
}
$customer->save();
@@ -221,55 +211,57 @@ private function get_cart_schema() {
'items' => array(
'type' => 'object',
'properties' => array(
- 'code' => array(
+ 'code' => array(
'description' => _x( 'The location code.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'title' => array(
- 'description' => _x( 'The location title.', 'shipments', 'woocommerce-germanized-shipments' ),
+ 'label' => array(
+ 'description' => _x( 'The location label.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'lat' => array(
+ 'latitude' => array(
'description' => _x( 'The location latitude.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'long' => array(
+ 'longitude' => array(
'description' => _x( 'The location longitude.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'needs_customer_number' => array(
- 'description' => _x( 'Whether the location needs a customer number or not.', 'shipments', 'woocommerce-germanized-shipments' ),
+ 'supports_customer_number' => array(
+ 'description' => _x( 'Whether the location supports a customer number or not.', 'shipments', 'woocommerce-germanized-shipments' ),
+ 'type' => 'boolean',
+ 'context' => array( 'view', 'edit' ),
+ 'readonly' => true,
+ 'default' => false,
+ ),
+ 'customer_number_is_mandatory' => array(
+ 'description' => _x( 'Whether the customer number is mandatory or not.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'default' => false,
),
- 'type' => array(
+ 'type' => array(
'description' => _x( 'The location type, e.g. locker.', 'shipments', 'woocommerce-germanized-shipments' ),
- 'type' => 'enum',
- 'enum' => array(
- 'locker',
- 'shop',
- 'servicepoint',
- ),
+ 'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'formatted_address' => array(
+ 'formatted_address' => array(
'description' => _x( 'The location\'s formatted address.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'address_replacements' => array(
+ 'address_replacements' => array(
'description' => _x( 'The location\'s address replacements.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
@@ -319,12 +311,13 @@ private function get_cart_schema() {
}
private function get_cart_data() {
- $customer = wc()->customer;
- $provider = false;
- $is_available = false;
- $locations = array();
+ $customer = wc()->customer;
+ $provider = false;
+ $is_available = false;
+ $locations = array();
+ $shipping_method = wc_gzd_get_current_shipping_provider_method();
- if ( $shipping_method = wc_gzd_get_current_shipping_provider_method() ) {
+ if ( $shipping_method ) {
$provider = $shipping_method->get_shipping_provider_instance();
}
@@ -336,13 +329,64 @@ private function get_cart_data() {
'city' => $customer->get_shipping_city(),
);
- $locations = $provider->get_pickup_locations( $address );
- $is_available = $provider->supports_pickup_location_delivery( $address );
+ $locations = $provider->get_pickup_locations( $address );
+ $max_weight = 0;
+ $max_dimensions = array(
+ 'length' => 0.0,
+ 'width' => 0.0,
+ 'height' => 0.0,
+ );
+
+ if ( ! empty( $locations ) && $shipping_method && is_a( $shipping_method->get_method(), 'Vendidero\Germanized\Shipments\ShippingMethod\ShippingMethod' ) ) {
+ $controller = new CartController();
+ $cart = wc()->cart;
+ $has_calculated_shipping = $cart->show_shipping();
+ $shipping_packages = $has_calculated_shipping ? $controller->get_shipping_packages() : array();
+ $current_rate_id = wc_gzd_get_current_shipping_method_id();
+
+ if ( isset( $shipping_packages[0]['rates'][ $current_rate_id ] ) ) {
+ $rate = $shipping_packages[0]['rates'][ $current_rate_id ];
+
+ if ( is_a( $rate, 'WC_Shipping_Rate' ) ) {
+ $meta = $rate->get_meta_data();
+
+ if ( isset( $meta['_packages'] ) ) {
+ foreach ( (array) $meta['_packages'] as $package_data ) {
+ $packaging_id = $package_data['packaging_id'];
+
+ if ( $packaging = wc_gzd_get_packaging( $packaging_id ) ) {
+ $package_weight = (float) wc_get_weight( $package_data['weight'], wc_gzd_get_packaging_weight_unit(), 'g' );
+
+ if ( (float) $packaging->get_length() > $max_dimensions['length'] ) {
+ $max_dimensions['length'] = (float) $packaging->get_length();
+ }
+ if ( (float) $packaging->get_width() > $max_dimensions['width'] ) {
+ $max_dimensions['width'] = (float) $packaging->get_width();
+ }
+ if ( (float) $packaging->get_height() > $max_dimensions['height'] ) {
+ $max_dimensions['height'] = (float) $packaging->get_height();
+ }
+
+ if ( $package_weight > $max_weight ) {
+ $max_weight = $package_weight;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $is_available = $provider->supports_pickup_location_delivery( $address, $max_dimensions, $max_weight );
}
return array(
'pickup_location_delivery_available' => $is_available && ! empty( $locations ),
- 'pickup_locations' => $locations,
+ 'pickup_locations' => array_map(
+ function( $location ) {
+ return $location->get_data(); },
+ $locations
+ ),
);
}
}
diff --git a/src/DataStores/Shipment.php b/src/DataStores/Shipment.php
index e30a9d57..28c01557 100644
--- a/src/DataStores/Shipment.php
+++ b/src/DataStores/Shipment.php
@@ -47,6 +47,8 @@ class Shipment extends WC_Data_Store_WP implements WC_Object_Data_Store_Interfac
'_weight_unit',
'_dimension_unit',
'_is_customer_requested',
+ '_pickup_location_code',
+ '_pickup_location_customer_number',
);
protected $core_props = array(
diff --git a/src/Interfaces/ShippingProviderAuto.php b/src/Interfaces/ShippingProviderAuto.php
index b187b6b0..4f36cadd 100644
--- a/src/Interfaces/ShippingProviderAuto.php
+++ b/src/Interfaces/ShippingProviderAuto.php
@@ -2,6 +2,7 @@
namespace Vendidero\Germanized\Shipments\Interfaces;
use Vendidero\Germanized\Shipments\Labels\ConfigurationSet;
+use Vendidero\Germanized\Shipments\ShippingProvider\PickupLocation;
/**
* Shipment Label Interface
@@ -47,15 +48,23 @@ public function is_sandbox();
public function get_settings_help_pointers( $section = '' );
- public function supports_pickup_location_delivery( $address, $max_dimensions = array() );
+ public function supports_pickup_location_delivery( $address, $max_dimensions = array(), $max_weight = 0.0 );
public function is_valid_pickup_location( $location_code, $address );
- public function is_valid_pickup_location_customer_number( $number );
-
- public function pickup_location_needs_customer_number( $location_code, $address );
-
+ /**
+ * @param $location_code
+ * @param $address
+ *
+ * @return PickupLocation|false
+ */
public function get_pickup_location_by_code( $location_code, $address );
+ /**
+ * @param $address
+ * @param $limit
+ *
+ * @return PickupLocation[]
+ */
public function get_pickup_locations( $address, $limit = 10 );
}
diff --git a/src/Order.php b/src/Order.php
index b0681848..94678f70 100644
--- a/src/Order.php
+++ b/src/Order.php
@@ -1124,6 +1124,44 @@ public function get_returnable_item_count() {
return apply_filters( 'woocommerce_gzd_shipment_order_returnable_item_count', $count, $this );
}
+ public function supports_pickup_location() {
+ $supports_pickup_location = false;
+
+ if ( $provider = wc_gzd_get_order_shipping_provider( $this ) ) {
+ if ( is_a( $provider, 'Vendidero\Germanized\Shipments\Interfaces\ShippingProviderAuto' ) ) {
+ $supports_pickup_location = $provider->supports_pickup_location_delivery( $this->get_order()->get_address( 'shipping' ) );
+ }
+ }
+
+ if ( $this->has_pickup_location() ) {
+ $supports_pickup_location = true;
+ }
+
+ return apply_filters( 'woocommerce_gzd_shipment_order_supports_pickup_location', $supports_pickup_location, $this->get_order(), $this );
+ }
+
+ public function has_pickup_location() {
+ $pickup_location_code = $this->get_pickup_location_code();
+
+ return apply_filters( 'woocommerce_gzd_shipment_order_has_pickup_location', ! empty( $pickup_location_code ), $this->get_order(), $this );
+ }
+
+ public function get_pickup_location_customer_number() {
+ $customer_number = '';
+
+ if ( $this->has_pickup_location() ) {
+ $customer_number = $this->get_order()->get_meta( '_pickup_location_customer_number', true );
+ }
+
+ return apply_filters( 'woocommerce_gzd_shipment_order_pickup_location_customer_number', $customer_number, $this->get_order(), $this );
+ }
+
+ public function get_pickup_location_code() {
+ $pickup_location_code = $this->get_order()->get_meta( '_pickup_location_code', true );
+
+ return apply_filters( 'woocommerce_gzd_shipment_order_pickup_location_code', $pickup_location_code, $this->get_order(), $this );
+ }
+
protected function has_local_pickup() {
$shipping_methods = $this->get_order()->get_shipping_methods();
$has_pickup = false;
diff --git a/src/Shipment.php b/src/Shipment.php
index b97fa422..320c0772 100644
--- a/src/Shipment.php
+++ b/src/Shipment.php
@@ -13,6 +13,7 @@
use Vendidero\Germanized\Shipments\Interfaces\ShipmentReturnLabel;
use Vendidero\Germanized\Shipments\Labels\Label;
use Vendidero\Germanized\Shipments\ShippingMethod\ProviderMethod;
+use Vendidero\Germanized\Shipments\ShippingProvider\PickupLocation;
use WC_Data;
use WC_Data_Store;
use Exception;
@@ -83,6 +84,8 @@ abstract class Shipment extends WC_Data {
protected $items_to_pack = null;
+ protected $pickup_location = null;
+
/**
* Item weights.
*
@@ -136,27 +139,29 @@ abstract class Shipment extends WC_Data {
* @var array
*/
protected $data = array(
- 'date_created' => null,
- 'date_sent' => null,
- 'status' => '',
- 'weight' => '',
- 'width' => '',
- 'height' => '',
- 'length' => '',
- 'packaging_weight' => '',
- 'weight_unit' => '',
- 'dimension_unit' => '',
- 'country' => '',
- 'address' => array(),
- 'tracking_id' => '',
- 'shipping_provider' => '',
- 'shipping_method' => '',
- 'total' => 0,
- 'subtotal' => 0,
- 'additional_total' => 0,
- 'est_delivery_date' => null,
- 'packaging_id' => 0,
- 'version' => '',
+ 'date_created' => null,
+ 'date_sent' => null,
+ 'status' => '',
+ 'weight' => '',
+ 'width' => '',
+ 'height' => '',
+ 'length' => '',
+ 'packaging_weight' => '',
+ 'weight_unit' => '',
+ 'dimension_unit' => '',
+ 'country' => '',
+ 'address' => array(),
+ 'tracking_id' => '',
+ 'shipping_provider' => '',
+ 'shipping_method' => '',
+ 'pickup_location_code' => '',
+ 'pickup_location_customer_number' => '',
+ 'total' => 0,
+ 'subtotal' => 0,
+ 'additional_total' => 0,
+ 'est_delivery_date' => null,
+ 'packaging_id' => 0,
+ 'version' => '',
);
/**
@@ -864,6 +869,51 @@ public function get_tracking_id( $context = 'view' ) {
return $this->get_prop( 'tracking_id', $context );
}
+ /**
+ * Retrieves the pickup location code, in case existent.
+ *
+ * @param string $context What the value is for. Valid values are 'view' and 'edit'.
+ * @return string
+ */
+ public function get_pickup_location_code( $context = 'view' ) {
+ return $this->get_prop( 'pickup_location_code', $context );
+ }
+
+ /**
+ * Retrieves the pickup location customer number, in case existent.
+ *
+ * @param string $context What the value is for. Valid values are 'view' and 'edit'.
+ * @return string
+ */
+ public function get_pickup_location_customer_number( $context = 'view' ) {
+ return $this->get_prop( 'pickup_location_customer_number', $context );
+ }
+
+ public function has_pickup_location() {
+ $code = $this->get_pickup_location_code();
+
+ return apply_filters( "{$this->get_general_hook_prefix()}has_pickup_location", ! empty( $code ), $this );
+ }
+
+ /**
+ * @return false|PickupLocation
+ */
+ public function get_pickup_location() {
+ if ( is_null( $this->pickup_location ) ) {
+ $this->pickup_location = false;
+
+ if ( $this->has_pickup_location() ) {
+ if ( $provider = $this->get_shipping_provider_instance() ) {
+ if ( is_a( $provider, 'Vendidero\Germanized\Shipments\Interfaces\ShippingProviderAuto' ) ) {
+ $this->pickup_location = $provider->get_pickup_location_by_code( $this->get_pickup_location_code(), $this->get_address() );
+ }
+ }
+ }
+ }
+
+ return $this->pickup_location;
+ }
+
/**
* Returns the shipment tracking URL.
*
@@ -1526,7 +1576,16 @@ public function get_est_delivery_date( $context = 'view' ) {
* @return boolean
*/
public function send_to_external_pickup( $types = array() ) {
- $types = is_array( $types ) ? $types : array( $types );
+ $types = is_array( $types ) ? $types : array( $types );
+ $has_pickup = $this->has_pickup_location();
+
+ if ( ! empty( $types ) ) {
+ $has_pickup = false;
+
+ if ( $location = $this->get_pickup_location() ) {
+ $has_pickup = in_array( $location->get_type(), $types, true );
+ }
+ }
/**
* Filter to decide whether a Shipment is to be sent to a external pickup location
@@ -1539,7 +1598,7 @@ public function send_to_external_pickup( $types = array() ) {
* @since 3.0.0
* @package Vendidero/Germanized/Shipments
*/
- return apply_filters( 'woocommerce_gzd_shipment_send_to_external_pickup', false, $types, $this );
+ return apply_filters( 'woocommerce_gzd_shipment_send_to_external_pickup', $has_pickup, $types, $this );
}
/**
@@ -1945,6 +2004,25 @@ public function set_tracking_id( $tracking_id ) {
$this->set_prop( 'tracking_id', $tracking_id );
}
+ /**
+ * Set shipment pickup location code.
+ *
+ * @param string $location_code The location code.
+ */
+ public function set_pickup_location_code( $location_code ) {
+ $this->set_prop( 'pickup_location_code', $location_code );
+ $this->pickup_location = null;
+ }
+
+ /**
+ * Set shipment pickup location customer number.
+ *
+ * @param string $customer_number The customer number.
+ */
+ public function set_pickup_location_customer_number( $customer_number ) {
+ $this->set_prop( 'pickup_location_customer_number', $customer_number );
+ }
+
/**
* Set shipment shipping provider.
*
diff --git a/src/ShippingMethod/ShippingMethod.php b/src/ShippingMethod/ShippingMethod.php
index 269b4625..9a195f74 100644
--- a/src/ShippingMethod/ShippingMethod.php
+++ b/src/ShippingMethod/ShippingMethod.php
@@ -681,11 +681,13 @@ public function calculate_shipping( $package = array() ) {
* included within the package.
*/
$item_map = array();
+ $weight = 0.0;
foreach ( $items as $item ) {
$cart_item_wrapper = $item->getItem();
$product = $cart_item_wrapper->get_product();
$product_key = $product->get_parent_id() . '_' . $product->get_id();
+ $weight += $cart_item_wrapper->getWeight();
if ( array_key_exists( $product_key, $item_map ) ) {
$item_map[ $product_key ]++;
@@ -706,6 +708,7 @@ public function calculate_shipping( $package = array() ) {
'packaging_id' => $packaging->get_id(),
'rules' => $package_applied_rules,
'items' => $item_map,
+ 'weight' => $weight + $packaging->getEmptyWeight(),
);
$rule_ids = array_unique( array_merge( $rule_ids, $package_applied_rules ) );
diff --git a/src/ShippingProvider/Auto.php b/src/ShippingProvider/Auto.php
index c1833b93..6bd40061 100644
--- a/src/ShippingProvider/Auto.php
+++ b/src/ShippingProvider/Auto.php
@@ -348,19 +348,33 @@ public function get_settings_help_pointers( $section = '' ) {
return array();
}
- public function supports_pickup_location_delivery( $address, $max_dimensions = array() ) {
+ public function supports_pickup_location_delivery( $address, $max_dimensions = array(), $max_weight = 0.0 ) {
return false;
}
+ /**
+ * @param $location_code
+ * @param $address
+ *
+ * @return PickupLocation|null
+ */
protected function fetch_pickup_location( $location_code, $address ) {
return null;
}
+ /**
+ * @param $location_code
+ * @param $address
+ *
+ * @return false|PickupLocation
+ */
public function get_pickup_location_by_code( $location_code, $address ) {
$address = $this->parse_pickup_location_address_args( $address );
$cache_key = $this->get_pickup_location_cache_key( $location_code, $address );
$pickup_location = get_transient( $cache_key );
+ $pickup_location = false;
+
if ( false === $pickup_location ) {
$pickup_location = $this->fetch_pickup_location( $location_code, $address );
@@ -369,6 +383,8 @@ public function get_pickup_location_by_code( $location_code, $address ) {
} else {
$pickup_location = false;
}
+ } elseif ( ! is_a( $pickup_location, 'Vendidero\Germanized\Shipments\ShippingProvider\PickupLocation' ) ) {
+ $pickup_location = false;
}
return $pickup_location;
@@ -393,20 +409,6 @@ protected function get_pickup_locations_cache_key( $address ) {
return $cache_key;
}
- public function is_valid_pickup_location_customer_number( $number ) {
- return true;
- }
-
- public function pickup_location_needs_customer_number( $location_code, $address ) {
- $needs_customer_number = false;
-
- if ( $pickup_location = $this->get_pickup_location_by_code( $location_code, $address ) ) {
- $needs_customer_number = $pickup_location['needs_customer_number'];
- }
-
- return $needs_customer_number;
- }
-
public function is_valid_pickup_location( $location_code, $address ) {
if ( $this->get_pickup_location_by_code( $location_code, $address ) ) {
return true;
@@ -436,6 +438,8 @@ public function get_pickup_locations( $address, $limit = 10 ) {
$pickup_locations = get_transient( $cache_key );
$address = $this->parse_pickup_location_address_args( $address );
+ $pickup_locations = false;
+
if ( false === $pickup_locations ) {
$pickup_locations = $this->fetch_pickup_locations( $address, $limit );
diff --git a/src/ShippingProvider/PickupLocation.php b/src/ShippingProvider/PickupLocation.php
new file mode 100644
index 00000000..a1562164
--- /dev/null
+++ b/src/ShippingProvider/PickupLocation.php
@@ -0,0 +1,180 @@
+ '',
+ 'type' => '',
+ 'label' => '',
+ 'latitude' => '',
+ 'longitude' => '',
+ 'supports_customer_number' => false,
+ 'customer_number_is_mandatory' => false,
+ 'customer_number_validation_cb' => null,
+ 'address' => array(),
+ 'address_replacement_map' => array(),
+ )
+ );
+
+ if ( empty( $args['code'] ) ) {
+ $args['code'] = sanitize_key( $args['label'] );
+ }
+
+ if ( empty( $args['code'] ) ) {
+ throw new \Exception( 'A pickup location needs a code.', 500 );
+ }
+
+ $this->code = $args['code'];
+ $this->type = $args['type'];
+ $this->label = $args['label'];
+ $this->latitude = $args['latitude'];
+ $this->longitude = $args['longitude'];
+ $this->supports_customer_number = wc_string_to_bool( $args['supports_customer_number'] );
+ $this->customer_number_is_mandatory = wc_string_to_bool( $args['customer_number_is_mandatory'] );
+ $this->customer_number_validation_cb = $args['customer_number_validation_cb'];
+ $this->address = wp_parse_args(
+ (array) $args['address'],
+ array(
+ 'address_1',
+ 'city',
+ 'postcode',
+ 'country',
+ )
+ );
+
+ if ( $this->customer_number_validation_cb instanceof \Closure ) {
+ throw new \Exception( 'Closures as callbacks for customer number validation are not supported', 500 );
+ }
+
+ $this->address_replacement_map = (array) $args['address_replacement_map'];
+ }
+
+ public function get_code() {
+ return $this->code;
+ }
+
+ public function get_label() {
+ return $this->label;
+ }
+
+ public function get_type() {
+ return $this->type;
+ }
+
+ public function get_address() {
+ return $this->address;
+ }
+
+ public function supports_customer_number() {
+ return $this->supports_customer_number;
+ }
+
+ public function customer_number_is_mandatory() {
+ return $this->customer_number_is_mandatory;
+ }
+
+ /**
+ * @param $customer_number
+ *
+ * @return bool|\WP_Error
+ */
+ public function customer_number_is_valid( $customer_number ) {
+ $is_valid = $this->customer_number_is_mandatory() ? ! empty( $customer_number ) : true;
+
+ if ( null !== $this->customer_number_validation_cb ) {
+ $is_valid = call_user_func_array( $this->customer_number_validation_cb, array( $customer_number, $this ) );
+ }
+
+ return $is_valid;
+ }
+
+ public function get_latitude() {
+ return $this->latitude;
+ }
+
+ public function get_longitude() {
+ return $this->longitude;
+ }
+
+ public function get_formatted_address( $separator = ', ' ) {
+ $address = $this->get_address();
+
+ if ( empty( $address['company'] ) ) {
+ $address['company'] = $this->get_label();
+ }
+
+ return WC()->countries->get_formatted_address( $address, $separator );
+ }
+
+ public function get_address_replacement_map() {
+ return $this->address_replacement_map;
+ }
+
+ public function get_address_replacements() {
+ $replacements = array();
+ $location_address = $this->get_address();
+ $location_address['label'] = $this->get_label();
+ $location_address['code'] = $this->get_code();
+
+ foreach ( $this->get_address_replacement_map() as $address_key => $location_address_key ) {
+ if ( isset( $location_address[ $location_address_key ] ) ) {
+ $replacements[ $address_key ] = $location_address[ $location_address_key ];
+ }
+ }
+
+ return $replacements;
+ }
+
+ public function replace_address( $object ) {
+ foreach ( $this->get_address_replacements() as $address_field => $address_value ) {
+ $setter = "set_shipping_{$address_field}";
+
+ if ( is_callable( array( $object, $setter ) ) ) {
+ $object->{$setter}( $address_value );
+ }
+ }
+ }
+
+ public function get_data() {
+ return array(
+ 'code' => $this->get_code(),
+ 'type' => $this->get_type(),
+ 'label' => $this->get_label(),
+ 'latitude' => $this->get_latitude(),
+ 'longitude' => $this->get_longitude(),
+ 'supports_customer_number' => $this->supports_customer_number(),
+ 'customer_number_is_mandatory' => $this->customer_number_is_mandatory(),
+ 'address' => $this->get_address(),
+ 'address_replacement_map' => $this->get_address_replacement_map(),
+ 'address_replacements' => $this->get_address_replacements(),
+ 'formatted_address' => $this->get_formatted_address(),
+ );
+ }
+}
diff --git a/src/SimpleShipment.php b/src/SimpleShipment.php
index e83d05ea..cf8c8a52 100644
--- a/src/SimpleShipment.php
+++ b/src/SimpleShipment.php
@@ -173,18 +173,20 @@ public function sync( $args = array() ) {
$args = wp_parse_args(
$args,
array(
- 'order_id' => $order->get_id(),
- 'shipping_method' => wc_gzd_get_shipment_order_shipping_method_id( $order ),
- 'shipping_provider' => ( ! empty( $provider ) ) ? $provider : $default_provider,
- 'packaging_id' => $this->get_packaging_id( 'edit' ),
- 'address' => $address_data,
- 'country' => $country,
- 'weight' => $this->get_weight( 'edit' ),
- 'packaging_weight' => $this->get_packaging_weight( 'edit' ),
- 'length' => $dimensions['length'],
- 'width' => $dimensions['width'],
- 'height' => $dimensions['height'],
- 'additional_total' => $order_shipment->calculate_shipment_additional_total( $this ),
+ 'order_id' => $order->get_id(),
+ 'shipping_method' => wc_gzd_get_shipment_order_shipping_method_id( $order ),
+ 'shipping_provider' => ( ! empty( $provider ) ) ? $provider : $default_provider,
+ 'packaging_id' => $this->get_packaging_id( 'edit' ),
+ 'address' => $address_data,
+ 'country' => $country,
+ 'weight' => $this->get_weight( 'edit' ),
+ 'packaging_weight' => $this->get_packaging_weight( 'edit' ),
+ 'pickup_location_code' => $order_shipment->has_pickup_location() ? $order_shipment->get_pickup_location_code() : '',
+ 'pickup_location_customer_number' => $order_shipment->has_pickup_location() ? $order_shipment->get_pickup_location_customer_number() : '',
+ 'length' => $dimensions['length'],
+ 'width' => $dimensions['width'],
+ 'height' => $dimensions['height'],
+ 'additional_total' => $order_shipment->calculate_shipment_additional_total( $this ),
)
);