Skip to content

Commit 7ce8214

Browse files
authored
Merge pull request #380 from kidunot89/feature/itemized-cart-tax
Feature/itemized cart tax
2 parents 8591ea1 + eed6061 commit 7ce8214

File tree

5 files changed

+114
-6
lines changed

5 files changed

+114
-6
lines changed

includes/mutation/class-cart-empty.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace WPGraphQL\WooCommerce\Mutation;
1212

13+
use GraphQL\Error\UserError;
1314
use GraphQL\Type\Definition\ResolveInfo;
1415
use WPGraphQL\AppContext;
1516
use WPGraphQL\WooCommerce\Data\Mutation\Cart_Mutation;
@@ -26,7 +27,9 @@ public static function register_mutation() {
2627
register_graphql_mutation(
2728
'emptyCart',
2829
array(
29-
'inputFields' => array(),
30+
'inputFields' => array(
31+
'clearPersistentCart' => array( 'type' => 'Boolean' )
32+
),
3033
'outputFields' => self::get_output_fields(),
3134
'mutateAndGetPayload' => self::mutate_and_get_payload(),
3235
)
@@ -44,7 +47,7 @@ public static function get_output_fields() {
4447
'cart' => array(
4548
'type' => 'Cart',
4649
'resolve' => function () {
47-
return Factory::resolve_cart();
50+
return \WC()->cart;
4851
},
4952
)
5053
);
@@ -62,6 +65,10 @@ public static function mutate_and_get_payload() {
6265
// Get/Clone WC_Cart instance.
6366
$cloned_cart = clone \WC()->cart;
6467

68+
if ( $cloned_cart->is_empty() ) {
69+
throw new UserError( __( 'Cart is empty', 'wp-graphql-woocommerce' ) );
70+
}
71+
6572
/**
6673
* Action fired before cart was cleared/emptied.
6774
*
@@ -73,7 +80,8 @@ public static function mutate_and_get_payload() {
7380
do_action( 'graphql_woocommerce_before_empty_cart', $cloned_cart, $input, $context, $info );
7481

7582
// Empty cart.
76-
\WC()->cart->empty_cart();
83+
$clear_persistent_cart = ! empty( $input['clearPersistentCart'] ) ? $input['clearPersistentCart'] : true;
84+
\WC()->cart->empty_cart( $clear_persistent_cart );
7785

7886
/**
7987
* Action fired after cart was cleared/emptied.

includes/type/object/class-cart-type.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Cart_Type {
2525
*/
2626
public static function register() {
2727
self::register_cart_fee();
28+
self::register_cart_tax();
2829
self::register_cart_item();
2930
self::register_cart();
3031
}
@@ -50,7 +51,7 @@ public static function register_cart() {
5051
'type' => 'String',
5152
'description' => __( 'Cart subtotal tax', 'wp-graphql-woocommerce' ),
5253
'resolve' => function( $source ) {
53-
$price = is_null( $source->get_subtotal_tax() ) ? $source->get_subtotal_tax() : 0;
54+
$price = ! is_null( $source->get_subtotal_tax() ) ? $source->get_subtotal_tax() : 0;
5455
return \wc_graphql_price( $price );
5556
},
5657
),
@@ -172,6 +173,14 @@ public static function register_cart() {
172173
return \wc_graphql_price( $price );
173174
},
174175
),
176+
'totalTaxes' => array(
177+
'type' => array( 'list_of' => 'CartTax' ),
178+
'description' => __( 'Cart total taxes itemized', 'wp-graphql-woocommerce' ),
179+
'resolve' => function( $source ) {
180+
$taxes = $source->get_tax_totals();
181+
return ! empty( $taxes ) ? array_values( $taxes ) : null;
182+
},
183+
),
175184
'isEmpty' => array(
176185
'type' => 'Boolean',
177186
'description' => __( 'Is cart empty', 'wp-graphql-woocommerce' ),
@@ -343,4 +352,45 @@ public static function register_cart_fee() {
343352
)
344353
);
345354
}
355+
/**
356+
* Registers CartTax type
357+
*/
358+
public static function register_cart_tax() {
359+
register_graphql_object_type(
360+
'CartTax',
361+
array(
362+
'description' => __( 'An itemized cart tax item', 'wp-graphql-woocommerce' ),
363+
'fields' => array(
364+
'id' => array(
365+
'type' => array( 'non_null' => 'ID' ),
366+
'description' => __( 'Tax Rate ID', 'wp-graphql-woocommerce' ),
367+
'resolve' => function( $source ) {
368+
return ! empty( $source->tax_rate_id ) ? $source->tax_rate_id : null;
369+
},
370+
),
371+
'label' => array(
372+
'type' => array( 'non_null' => 'String' ),
373+
'description' => __( 'Tax label', 'wp-graphql-woocommerce' ),
374+
'resolve' => function( $source ) {
375+
return ! empty( $source->label ) ? $source->label : null;
376+
},
377+
),
378+
'isCompound' => array(
379+
'type' => 'Boolean',
380+
'description' => __( 'Is tax compound?', 'wp-graphql-woocommerce' ),
381+
'resolve' => function( $source ) {
382+
return ! empty( $source->is_compound ) ? $source->is_compound : null;
383+
},
384+
),
385+
'amount' => array(
386+
'type' => 'String',
387+
'description' => __( 'Tax amount', 'wp-graphql-woocommerce' ),
388+
'resolve' => function( $source ) {
389+
return ! empty( $source->amount ) ? \wc_graphql_price( $source->amount ) : null;
390+
},
391+
),
392+
),
393+
)
394+
);
395+
}
346396
}

includes/type/object/class-root-query.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,25 @@ public static function register_fields() {
2727
array(
2828
'cart' => array(
2929
'type' => 'Cart',
30+
'args' => array(
31+
'recalculateTotals' => array(
32+
'type' => 'Boolean',
33+
'description' => __( 'Should cart totals be recalculated.', 'wp-graphql-woocommerce' ),
34+
),
35+
),
3036
'description' => __( 'The cart object', 'wp-graphql-woocommerce' ),
31-
'resolve' => function() {
37+
'resolve' => function( $_, $args ) {
3238
$token_invalid = apply_filters( 'graphql_woocommerce_session_token_errors', null );
3339
if ( $token_invalid ) {
3440
throw new UserError( $token_invalid );
3541
}
3642

37-
return Factory::resolve_cart();
43+
$cart = Factory::resolve_cart();
44+
if ( ! empty( $args['recalculateTotals'] ) && $args['recalculateTotals'] ) {
45+
$cart->calculate_totals();
46+
}
47+
48+
return $cart;
3849
},
3950
),
4051
'cartItem' => array(

tests/_support/Helper/crud-helpers/cart.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ public function print_query( $id = 0 ) {
5151
'isEmpty' => $cart->is_empty(),
5252
'displayPricesIncludeTax' => $cart->display_prices_including_tax(),
5353
'needsShippingAddress' => $cart->needs_shipping_address(),
54+
'totalTaxes' => ! empty( $cart->get_tax_totals() )
55+
? array_map(
56+
function( $tax_data ) {
57+
return array(
58+
'id' => $tax_data->tax_rate_id,
59+
'label' => $tax_data->label,
60+
'isCompound' => $tax_data->is_compound,
61+
'amount' => \wc_graphql_price( $tax_data->amount ),
62+
);
63+
},
64+
array_values( $cart->get_tax_totals() )
65+
)
66+
: null,
5467
);
5568
}
5669

tests/wpunit/CartQueriesTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ public function setUp() {
1818
$this->variation_helper = $this->getModule('\Helper\Wpunit')->product_variation();
1919
$this->coupon_helper = $this->getModule('\Helper\Wpunit')->coupon();
2020
$this->helper = $this->getModule('\Helper\Wpunit')->cart();
21+
$this->tax = $this->getModule('\Helper\Wpunit')->tax_rate();
22+
23+
// Turn on tax calculations. Important!
24+
update_option( 'woocommerce_prices_include_tax', 'no' );
25+
update_option( 'woocommerce_calc_taxes', 'yes' );
26+
update_option( 'woocommerce_tax_round_at_subtotal', 'no' );
27+
28+
// Create a tax rate.
29+
$this->tax->create(
30+
array(
31+
'country' => '',
32+
'state' => '',
33+
'rate' => 20.000,
34+
'name' => 'VAT',
35+
'priority' => '1',
36+
'compound' => '0',
37+
'shipping' => '1',
38+
'class' => ''
39+
)
40+
);
2141
}
2242

2343
public function tearDown() {
@@ -55,6 +75,12 @@ public function testCartQuery() {
5575
isEmpty
5676
displayPricesIncludeTax
5777
needsShippingAddress
78+
totalTaxes {
79+
id
80+
isCompound
81+
amount
82+
label
83+
}
5884
}
5985
}
6086
';

0 commit comments

Comments
 (0)