Skip to content

Commit

Permalink
Added validation + order adjustments.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisnissle committed Mar 26, 2024
1 parent bf35abe commit 685e69e
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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';
Expand All @@ -17,7 +18,7 @@ import {

import { decodeEntities } from '@wordpress/html-entities';
import { useDebouncedCallback, useDebounce } from 'use-debounce';
import { getSelectedShippingProviders, Combobox } from '@woocommerceGzdShipments/blocks-checkout';
import { getSelectedShippingProviders, Combobox, hasShippingProvider } from '@woocommerceGzdShipments/blocks-checkout';

const PickupLocationSelect = ({
extensions,
Expand Down Expand Up @@ -94,6 +95,19 @@ const PickupLocationSelect = ({
const shippingAddress = customerData.shippingAddress;
const { setShippingAddress, setBillingAddress } = useDispatch( CART_STORE_KEY );

useEffect(() => {
if ( checkoutOptions.pickup_location ) {
const currentLocation = getLocationByCode( checkoutOptions.pickup_location );

if ( ! currentLocation ) {
setOption( 'pickup_location', '' );
setOption( 'pickup_location_customer_number', '' );
}
}
}, [
locationOptions
] );

useEffect(() => {
if ( checkoutOptions.pickup_location ) {
const currentLocation = getLocationByCode( checkoutOptions.pickup_location );
Expand Down Expand Up @@ -142,7 +156,7 @@ const PickupLocationSelect = ({
pickupLocationDeliveryAvailable
] );

console.log( checkoutOptions );
console.log(checkoutOptions);

if ( needsShipping && pickupLocationDeliveryAvailable ) {
return (
Expand All @@ -159,8 +173,6 @@ const PickupLocationSelect = ({
value={ checkoutOptions.pickup_location }
required={ false }
onChange={ ( newLocationCode ) => {
console.log('On change: ' + newLocationCode);

if ( availableLocations.hasOwnProperty( newLocationCode ) ) {
setOption( 'pickup_location', newLocationCode );
} else {
Expand Down
1 change: 1 addition & 0 deletions assets/js/packages/checkout/components/combobox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const Combobox = ( {
className,
label,
onChange,
onSearch = null,
options,
value,
required = false,
Expand Down
175 changes: 155 additions & 20 deletions src/Blocks/Checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,139 @@ final class Checkout {
public function __construct() {
$this->register_endpoint_data();
$this->register_integrations();
$this->register_validation_and_storage();
}

private function register_validation_and_storage() {
add_action(
'woocommerce_store_api_checkout_update_order_from_request',
function( $order, $request ) {
$this->validate_checkout_data( $order, $request );
},
10,
2
);
}

private function has_checkout_data( $param, $request ) {
$request_data = isset( $request['extensions']['woocommerce-gzd-shipments'] ) ? (array) $request['extensions']['woocommerce-gzd-shipments'] : array();

return isset( $request_data[ $param ] ) && null !== $request_data[ $param ];
}

/**
* @param \WP_REST_Request $request
*
* @return array
*/
private function get_checkout_data_from_request( $request ) {
$data = array_filter( (array) wc_clean( $request['extensions']['woocommerce-gzd-shipments'] ) );
$data = wp_parse_args(
$data,
array(
'pickup_location' => '',
'pickup_location_customer_number' => '',
)
);

return $data;
}

/**
* @param \WC_Order $order
* @param \WP_REST_Request $request
*
* @return void
*/
private function validate_checkout_data( $order, $request ) {
$gzd_data = $this->get_checkout_data_from_request( $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;
$is_valid = false;
$pickup_location = false;
$address_data = array(
'country' => $order->get_shipping_country(),
'postcode' => $order->get_shipping_postcode(),
'city' => $order->get_shipping_city(),
'address_1' => $order->get_shipping_address_1(),
);

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 );

if ( $is_valid && $needs_customer_number ) {
if ( ! $provider->is_valid_pickup_location_customer_number( $pickup_location_customer_number ) ) {
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 );
}
}

$order->update_meta_data( '_pickup_location_code', $pickup_location_code );

if ( $needs_customer_number ) {
$order->update_meta_data( '_pickup_location_customer_number', $pickup_location_customer_number );
}

/**
* Persist customer changes for logged-in customers.
*/
if ( $order->get_customer_id() ) {
$wc_customer = new \WC_Customer( $order->get_customer_id() );

$wc_customer->update_meta_data( 'pickup_location_code', $pickup_location_code );

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 ) {
$wc_customer->update_meta_data( 'pickup_location_customer_number', $pickup_location_customer_number );
}

$wc_customer->save();
}

$customer = wc()->customer;
$customer->update_meta_data( 'pickup_location_code', $pickup_location_code );

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 ) {
$customer->update_meta_data( 'pickup_location_customer_number', $pickup_location_customer_number );
}
$customer->save();
} else {
throw new \Automattic\WooCommerce\StoreApi\Exceptions\RouteException( 'pickup_location_unknown', _x( 'Sorry, your current pickup location is not supported.', 'shipments', 'woocommerce-germanized-shipments' ), 400 );
}
}
}

private function register_integrations() {
Expand Down Expand Up @@ -57,7 +190,7 @@ private function register_endpoint_data() {

private function get_checkout_schema() {
return array(
'pickup_location' => array(
'pickup_location' => array(
'description' => _x( 'Pickup location', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => array( 'string', 'null' ),
'context' => array( 'view', 'edit' ),
Expand All @@ -80,85 +213,85 @@ private function get_cart_schema() {
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'pickup_locations' => array(
'pickup_locations' => array(
'description' => _x( 'Available pickup locations', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'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(
'title' => array(
'description' => _x( 'The location title.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'lat' => array(
'lat' => array(
'description' => _x( 'The location latitude.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'long' => array(
'long' => array(
'description' => _x( 'The location longitude.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'needs_customer_number' => array(
'needs_customer_number' => array(
'description' => _x( 'Whether the location needs a customer number 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'
'servicepoint',
),
'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' ),
'readonly' => true,
'items' => array(
'type' => 'object',
'properties' => array(
'address_1' => array(
'address_1' => array(
'description' => _x( 'The location address.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'default' => '',
),
'address_2' => array(
'address_2' => array(
'description' => _x( 'The location address 2.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'default' => '',
),
'postcode' => array(
'postcode' => array(
'description' => _x( 'The location postcode.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
Expand All @@ -170,14 +303,14 @@ private function get_cart_schema() {
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'country' => array(
'country' => array(
'description' => _x( 'The location country.', 'shipments', 'woocommerce-germanized-shipments' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
)
)
)
),
),
),
),
),
),
Expand All @@ -197,8 +330,10 @@ private function get_cart_data() {

if ( $provider && is_a( $provider, '\Vendidero\Germanized\Shipments\Interfaces\ShippingProviderAuto' ) ) {
$address = array(
'postcode' => $customer->get_shipping_postcode(),
'country' => $customer->get_shipping_country(),
'postcode' => $customer->get_shipping_postcode(),
'country' => $customer->get_shipping_country(),
'address_1' => $customer->get_shipping_address_1(),
'city' => $customer->get_shipping_city(),
);

$locations = $provider->get_pickup_locations( $address );
Expand Down
6 changes: 6 additions & 0 deletions src/Interfaces/ShippingProviderAuto.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,11 @@ public function supports_pickup_location_delivery( $address, $max_dimensions = a

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 );

public function get_pickup_location_by_code( $location_code, $address );

public function get_pickup_locations( $address, $limit = 10 );
}
Loading

0 comments on commit 685e69e

Please sign in to comment.