Skip to content

Commit

Permalink
Add coupon code condition rule and element query param
Browse files Browse the repository at this point in the history
  • Loading branch information
nfourtythree committed Nov 18, 2024
1 parent e98efbb commit 9f0e2be
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 3 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Release Notes for Craft Commerce (WIP)

## Administration
### Administration
- Added a new "Coupon Code" order condition rule. ([#3776](https://github.com/craftcms/commerce/discussions/3776))
- Added a new "Payment Gateway" order condition rule. ([#3722](https://github.com/craftcms/commerce/discussions/3722))

- Added a new "Payment Gateway" order condition rule. ([#3722](https://github.com/craftcms/commerce/discussions/3722))
### Development
- Added the `couponCode` order query param.

### Extensibility
- Added `craft\commerce\elements\conditions\orders\CouponCodeConditionRule`.
- Added `craft\commerce\elements\db\OrderQuery::$couponCode`.
- Added `craft\commerce\elements\db\OrderQuery::couponCode()`.
29 changes: 29 additions & 0 deletions src/elements/conditions/orders/CouponCodeConditionRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* @link https://craftcms.com/
* @copyright Copyright (c) Pixel & Tonic, Inc.
* @license https://craftcms.github.io/license/
*/

namespace craft\commerce\elements\conditions\orders;

use Craft;

/**
* Order Coupon Code condition rule.
*
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com>
* @since 5.3.0
*/
class CouponCodeConditionRule extends OrderTextValuesAttributeConditionRule
{
public string $orderAttribute = 'couponCode';

/**
* @inheritdoc
*/
public function getLabel(): string
{
return Craft::t('commerce', 'Coupon Code');
}
}
3 changes: 2 additions & 1 deletion src/elements/conditions/orders/OrderCondition.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ protected function selectableConditionRules(): array
{
return array_merge(parent::selectableConditionRules(), [
DateOrderedConditionRule::class,
CustomerConditionRule::class,
CompletedConditionRule::class,
CouponCodeConditionRule::class,
CustomerConditionRule::class,
PaidConditionRule::class,
HasPurchasableConditionRule::class,
ItemSubtotalConditionRule::class,
Expand Down
52 changes: 52 additions & 0 deletions src/elements/db/OrderQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ class OrderQuery extends ElementQuery
*/
public mixed $reference = null;

/**
* @var mixed The order reference of the resulting order.
* @used-by couponCode()
*/
public mixed $couponCode = null;

/**
* @var mixed The email address the resulting orders must have.
*/
Expand Down Expand Up @@ -372,6 +378,48 @@ public function reference(mixed $value): OrderQuery
return $this;
}

/**
* Narrows the query results based on the order's coupon code.
*
* Possible values include:
*
* | Value | Fetches {elements}…
* | - | -
* | `':empty:'` | that don’t have a coupon code.
* | `':notempty:'` | that have a coupon code.
* | `'Foo'` | with a coupon code of `Foo`.
* | `'Foo*'` | with a coupon code that begins with `Foo`.
* | `'*Foo'` | with a coupon code that ends with `Foo`.
* | `'*Foo*'` | with a coupon code that contains `Foo`.
* | `'not *Foo*'` | with a coupon code that doesn’t contain `Foo`.
* | `['*Foo*', '*Bar*']` | with a coupon code that contains `Foo` or `Bar`.
* | `['not', '*Foo*', '*Bar*']` | with a coupon code that doesn’t contain `Foo` or `Bar`.
*
* ---
*
* ```twig
* {# Fetch the requested {element} #}
* {% set {element-var} = {twig-method}
* .reference('foo')
* .one() %}
* ```
*
* ```php
* // Fetch the requested {element}
* ${element-var} = {php-method}
* ->reference('foo')
* ->one();
* ```
*
* @param string|null $value The property value
* @return static self reference
*/
public function couponCode(mixed $value): OrderQuery
{
$this->couponCode = $value;
return $this;
}

/**
* Narrows the query results based on the customers’ email addresses.
*
Expand Down Expand Up @@ -1603,6 +1651,10 @@ protected function beforePrepare(): bool
$this->subQuery->andWhere(Db::parseParam('commerce_orders.reference', $this->reference));
}

if (isset($this->couponCode)) {
$this->subQuery->andWhere(Db::parseParam('commerce_orders.couponCode', $this->couponCode));
}

if (isset($this->email) && $this->email) {
// Join and search the users table for email address
$this->subQuery->leftJoin(CraftTable::USERS . ' users', '[[users.id]] = [[commerce_orders.customerId]]');
Expand Down
39 changes: 39 additions & 0 deletions tests/unit/elements/order/OrderQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,45 @@ public function emailDataProvider(): array
];
}

/**
* @param string $couponCode
* @param int $count
* @return void
* @dataProvider couponCodeDataProvider
*/
public function testCouponCode(?string $couponCode, int $count): void
{
$ordersFixture = $this->tester->grabFixture('orders');
/** @var Order $order */
$order = $ordersFixture->getElement('completed-new');

// Temporarily add a coupon code to an order
\craft\commerce\records\Order::updateAll(['couponCode' => 'foo'], ['id' => $order->id]);

$orderQuery = Order::find();
$orderQuery->couponCode($couponCode);

self::assertCount($count, $orderQuery->all());

// Remove temporary coupon code
\craft\commerce\records\Order::updateAll(['couponCode' => null], ['id' => $order->id]);
}

/**
* @return array[]
*/
public function couponCodeDataProvider(): array
{
return [
'normal' => ['foo', 1],
'case-insensitive' => ['fOo', 1],
'using-null' => [null, 3],
'empty-code' => [':empty:', 2],
'not-empty-code' => [':notempty:', 1],
'no-results' => ['nope', 0],
];
}

/**
* @param mixed $handle
* @param int $count
Expand Down

0 comments on commit 9f0e2be

Please sign in to comment.