mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
feat: configurable createdVia on order mutations + WooCommerce order attribution (#1018)
* Add option to Change the created_via field.
Can be useful when WooCommerce is being used from multiply sources. For example, with plugins like Point of Sale for WooCommerce.
* feat: createdVia on checkout + WooCommerce order attribution origin
Builds on the createOrder createdVia option:
- Add a createdVia input to the checkout mutation. WC_Checkout::create_order()
hardcodes created_via to 'checkout' after its data loop, so process_checkout()
overrides it (and tags the attribution source type) only when createdVia is
provided; otherwise checkout keeps WooCommerce's 'checkout' default.
- createOrder now defaults created_via to WooCommerce::get_order_attribution_source_type()
('graphql-api', filterable) and writes that value to the
_wc_order_attribution_source_type order meta so GraphQL orders are attributable.
- Register a wc_order_attribution_origin_label callback that brands orders
attributed to 'graphql-api' as the 'GraphQL' origin in WooCommerce admin.
- Cover createdVia + attribution in OrderMutationsTest and CheckoutMutationTest.
---------
Co-authored-by: Scott Kennedy <scottyzen@gmail.com>
This commit is contained in:
co-authored by
Scott Kennedy
parent
01876f5344
commit
2ce9424e11
@@ -47,6 +47,41 @@ class WooCommerce {
|
||||
// WPGraphQL Reset password -> Use woocommerce email password template when requested.
|
||||
add_filter( 'retrieve_password_message', [ self::class, 'get_reset_password_message' ], 10, 3 );
|
||||
add_filter( 'retrieve_password_title', [ self::class, 'get_reset_password_title' ] );
|
||||
|
||||
// Brand the WooCommerce Order Attribution "Origin" for orders created through WPGraphQL.
|
||||
add_filter( 'wc_order_attribution_origin_label', [ self::class, 'order_attribution_origin_label' ], 10, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WooCommerce Order Attribution source type used to mark orders created through WPGraphQL.
|
||||
*
|
||||
* Matches the default `created_via` value so GraphQL-created orders are attributable out of the box.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_order_attribution_source_type() {
|
||||
return apply_filters( 'graphql_woocommerce_order_attribution_source_type', 'graphql-api' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the WooCommerce Order Attribution "Origin" label for orders created through WPGraphQL.
|
||||
*
|
||||
* Connected to WooCommerce's order origin label filter so orders tagged with our attribution
|
||||
* source type surface a recognizable origin instead of "Unknown".
|
||||
*
|
||||
* @param string $label Origin label. May contain a "%s" placeholder for the source.
|
||||
* @param string $source_type Attribution source type.
|
||||
* @param string $source Attribution source.
|
||||
* @param string $formatted_source Formatted attribution source.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function order_attribution_origin_label( $label, $source_type, $source, $formatted_source ) {
|
||||
if ( self::get_order_attribution_source_type() !== $source_type ) {
|
||||
return $label;
|
||||
}
|
||||
|
||||
return apply_filters( 'graphql_woocommerce_order_attribution_origin_label', __( 'GraphQL', 'wp-graphql-woocommerce' ), $source, $formatted_source );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -649,6 +649,13 @@ class Checkout_Mutation {
|
||||
throw new UserError( __( 'Unable to create order.', 'wp-graphql-woocommerce' ) );
|
||||
}
|
||||
|
||||
// Override the "created via" source when provided. WC_Checkout::create_order() hardcodes it to "checkout".
|
||||
if ( ! empty( $input['createdVia'] ) ) {
|
||||
$order->set_created_via( $input['createdVia'] );
|
||||
$order->add_meta_data( '_wc_order_attribution_source_type', $input['createdVia'], true );
|
||||
$order->save();
|
||||
}
|
||||
|
||||
// Add meta data.
|
||||
if ( ! empty( $input['metaData'] ) ) {
|
||||
self::update_order_meta( $order_id, $input['metaData'], $input, $context, $info );
|
||||
|
||||
@@ -111,6 +111,12 @@ class Checkout {
|
||||
return __( 'Fees to add to the order.', 'wp-graphql-woocommerce' );
|
||||
},
|
||||
],
|
||||
'createdVia' => [
|
||||
'type' => 'String',
|
||||
'description' => static function () {
|
||||
return __( 'Source of the order. Useful when WooCommerce is driven from multiple sources. Defaults to "checkout".', 'wp-graphql-woocommerce' );
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ use WC_Order_Factory;
|
||||
use WPGraphQL\AppContext;
|
||||
use WPGraphQL\WooCommerce\Data\Mutation\Order_Mutation;
|
||||
use WPGraphQL\WooCommerce\Model\Order;
|
||||
use WPGraphQL\WooCommerce\WooCommerce;
|
||||
|
||||
/**
|
||||
* Class Order_Create
|
||||
@@ -140,6 +141,12 @@ class Order_Create {
|
||||
return __( 'Define if the order is paid. It will set the status to processing and reduce stock items.', 'wp-graphql-woocommerce' );
|
||||
},
|
||||
],
|
||||
'createdVia' => [
|
||||
'type' => 'String',
|
||||
'description' => static function () {
|
||||
return __( 'Source of the order. Useful when WooCommerce is driven from multiple sources. Defaults to "graphql-api".', 'wp-graphql-woocommerce' );
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -203,7 +210,9 @@ class Order_Create {
|
||||
Order_Mutation::apply_coupons( $order, $input['coupons'] );
|
||||
}
|
||||
|
||||
$order->set_created_via( 'graphql-api' );
|
||||
$created_via = ! empty( $input['createdVia'] ) ? $input['createdVia'] : WooCommerce::get_order_attribution_source_type();
|
||||
$order->set_created_via( $created_via );
|
||||
$order->add_meta_data( '_wc_order_attribution_source_type', $created_via, true );
|
||||
$order->set_prices_include_tax( 'yes' === get_option( 'woocommerce_prices_include_tax' ) );
|
||||
$order->calculate_totals( true );
|
||||
|
||||
|
||||
@@ -505,6 +505,27 @@ class CheckoutMutationTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGrap
|
||||
$this->assertEquals( '555-555-6789', $order->get_shipping_phone() );
|
||||
}
|
||||
|
||||
public function testCheckoutMutationWithCreatedVia() {
|
||||
$this->loginAsCustomer();
|
||||
|
||||
$product_id = $this->factory->product->createSimple();
|
||||
WC()->cart->add_to_cart( $product_id, 1 );
|
||||
|
||||
$variables = [ 'input' => $this->getCheckoutInput( [ 'createdVia' => 'pos' ] ) ];
|
||||
$query = $this->getCheckoutMutation();
|
||||
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$this->assertQuerySuccessful(
|
||||
$response,
|
||||
[ $this->expectedField( 'checkout.order.createdVia', 'pos' ) ]
|
||||
);
|
||||
|
||||
// The provided "createdVia" overrides WooCommerce's hardcoded "checkout" source and tags the attribution source type.
|
||||
$order = \wc_get_order( $response['data']['checkout']['order']['databaseId'] );
|
||||
$this->assertEquals( 'pos', $order->get_created_via() );
|
||||
$this->assertEquals( 'pos', $order->get_meta( '_wc_order_attribution_source_type' ) );
|
||||
}
|
||||
|
||||
public function testCheckoutMutationWithNewAccount() {
|
||||
$variable = $this->factory->product_variation->createSome();
|
||||
$product_ids = [
|
||||
|
||||
@@ -351,8 +351,12 @@ class OrderMutationsTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGraphQ
|
||||
$this->expectedField( 'createOrder.order.shipping.country', 'US' ),
|
||||
$this->expectedField( 'createOrder.order.paymentMethod', 'bacs' ),
|
||||
$this->expectedField( 'createOrder.order.paymentMethodTitle', 'Direct Bank Transfer' ),
|
||||
$this->expectedField( 'createOrder.order.createdVia', 'graphql-api' ),
|
||||
];
|
||||
|
||||
// The order is attributed to the "graphql-api" source so WooCommerce surfaces the "GraphQL" origin.
|
||||
$this->assertEquals( 'graphql-api', $order->get_meta( '_wc_order_attribution_source_type' ) );
|
||||
|
||||
// Validate coupon lines.
|
||||
$coupon_items = array_values( $order->get_items( 'coupon' ) );
|
||||
foreach ( $coupon_items as $i => $item ) {
|
||||
@@ -412,6 +416,38 @@ class OrderMutationsTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGraphQ
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
}
|
||||
|
||||
public function testCreateOrderMutationWithCreatedVia() {
|
||||
$this->loginAsShopManager();
|
||||
|
||||
$product_id = $this->factory->product->createSimple();
|
||||
$input = [
|
||||
'createdVia' => 'pos',
|
||||
'lineItems' => [
|
||||
[
|
||||
'productId' => $product_id,
|
||||
'quantity' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->orderMutation( $input );
|
||||
$this->assertQuerySuccessful(
|
||||
$response,
|
||||
[ $this->expectedField( 'createOrder.order.createdVia', 'pos' ) ]
|
||||
);
|
||||
|
||||
// A provided "createdVia" flows into both the order source and the WooCommerce attribution source type.
|
||||
$order = \WC_Order_Factory::get_order( $response['data']['createOrder']['order']['databaseId'] );
|
||||
$this->assertEquals( 'pos', $order->get_created_via() );
|
||||
$this->assertEquals( 'pos', $order->get_meta( '_wc_order_attribution_source_type' ) );
|
||||
|
||||
// Orders attributed to "graphql-api" surface a branded "GraphQL" origin in WooCommerce.
|
||||
$this->assertEquals(
|
||||
'GraphQL',
|
||||
apply_filters( 'wc_order_attribution_origin_label', 'Unknown', 'graphql-api', '', 'Unknown' )
|
||||
);
|
||||
}
|
||||
|
||||
public function testUpdateOrderMutation() {
|
||||
// Create products and coupons to be used in order creation.
|
||||
$variable = $this->factory->product_variation->createSome( $this->factory->product->createVariable() );
|
||||
|
||||
Reference in New Issue
Block a user