Skip to content

Instantly share code, notes, and snippets.

@hendrikeng
Last active September 20, 2019 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hendrikeng/4e02199fda7c4171fb31fb53b2ff0520 to your computer and use it in GitHub Desktop.
Save hendrikeng/4e02199fda7c4171fb31fb53b2ff0520 to your computer and use it in GitHub Desktop.
Discount Plugin and Adjuster
<?php
/**
* Friendsdiscount plugin for Craft CMS 3.x
*
* Price adjuster that gives discount if a specific product type has been purchased in a specific time frame
*
* @link https://github.com/hendrikeng
* @copyright Copyright (c) 2018 Hendrik Werner
*/
namespace hendrikeng\friendsdiscount;
use Craft;
use craft\base\Plugin;
use craft\services\Plugins;
use craft\events\PluginEvent;
use craft\commerce\services\OrderAdjustments;
use craft\events\RegisterComponentTypesEvent;
use hendrikeng\friendsdiscount\adjusters\FriendsDiscountAdjuster;
use yii\base\Event;
/**
* Craft plugins are very much like little applications in and of themselves. We’ve made
* it as simple as we can, but the training wheels are off. A little prior knowledge is
* going to be required to write a plugin.
*
* For the purposes of the plugin docs, we’re going to assume that you know PHP and SQL,
* as well as some semi-advanced concepts like object-oriented programming and PHP namespaces.
*
* https://craftcms.com/docs/plugins/introduction
*
* @author Hendrik Werner
* @package Friendsdiscount
* @since 1.0.0
*
*/
class Friendsdiscount extends Plugin
{
// Static Properties
// =========================================================================
/**
* Static property that is an instance of this plugin class so that it can be accessed via
* Friendsdiscount::$plugin
*
* @var Friendsdiscount
*/
public static $plugin;
// Public Properties
// =========================================================================
/**
* To execute your plugin’s migrations, you’ll need to increase its schema version.
*
* @var string
*/
public $schemaVersion = '1.0.0';
// Public Methods
// =========================================================================
/**
* Set our $plugin static property to this class so that it can be accessed via
* Friendsdiscount::$plugin
*
* Called after the plugin class is instantiated; do any one-time initialization
* here such as hooks and events.
*
* If you have a '/vendor/autoload.php' file, it will be loaded for you automatically;
* you do not need to load it in your init() method.
*
*/
public function init()
{
parent::init();
self::$plugin = $this;
// Do something after we're installed
Event::on(
Plugins::class,
Plugins::EVENT_AFTER_INSTALL_PLUGIN,
function(PluginEvent $event) {
if ($event->plugin === $this) {
// We were just installed
}
}
);
Event::on(
OrderAdjustments::class,
OrderAdjustments::EVENT_REGISTER_ORDER_ADJUSTERS,
function(RegisterComponentTypesEvent $event) {
$event->types[] = FriendsDiscountAdjuster::class;
}
);
/**
* Logging in Craft involves using one of the following methods:
*
* Craft::trace(): record a message to trace how a piece of code runs. This is mainly for development use.
* Craft::info(): record a message that conveys some useful information.
* Craft::warning(): record a warning message that indicates something unexpected has happened.
* Craft::error(): record a fatal error that should be investigated as soon as possible.
*
* Unless `devMode` is on, only Craft::warning() & Craft::error() will log to `craft/storage/logs/web.log`
*
* It's recommended that you pass in the magic constant `__METHOD__` as the second parameter, which sets
* the category to the method (prefixed with the fully qualified class name) where the constant appears.
*
* To enable the Yii debug toolbar, go to your user account in the AdminCP and check the
* [] Show the debug toolbar on the front end & [] Show the debug toolbar on the Control Panel
*
* http://www.yiiframework.com/doc-2.0/guide-runtime-logging.html
*/
Craft::info(
Craft::t(
'friendsdiscount',
'{name} plugin loaded',
['name' => $this->name]
),
__METHOD__
);
}
// Protected Methods
// =========================================================================
}
<?php
namespace craft\commerce\adjusters;
use Craft;
use craft\commerce\base\AdjusterInterface;
use craft\commerce\elements\Order;
use craft\commerce\models\OrderAdjustment;
use craft\commerce\Plugin;
class FriendsDiscountAdjuster implements AdjusterInterface
{
/**
* Check if the customer has lineItems with product.type 'donation'
* in his current cart and if the donation is more than $75.
*/
public function checkIfInCart($order)
{
// get current cart
$cart = Plugin::getInstance()->getCart();
$didDonate = false;
// get lineItems from current cart and check if rules apply
foreach ($cart->getLineItems() as $lineItem) {
$purchable = $lineItem->getPurchasable();
if ($purchable && $purchable instanceof \craft\commerce\elements\Variant && $purchable->getProduct()->getType()->handle == 'donation' && $purchable->getPrice() >= '75') {
$didDonate = true;
}
}
return $didDonate;
}
/**
* Check if the customer has bought a lineItem with product.type 'donation'
* in his previous orders and if the donation was more than $75.
* and not older than 365 days
*/
public function checkIfDonated($order)
{
// get users email
$email = $order->getEmail();
if (!$email) {
return false;
}
// get previous orders by users email
$orders = Plugin::getInstance()->getOrders()->getOrdersByEmail($email);
$didDonate = false;
// get pervious orders and check if rules apply
foreach ($orders as $previousOrder) {
// get amount of days since the order has been placed
$timeDiff = abs(strtotime(date('Y/m/d', time())) - strtotime($previousOrder->dateOrdered->format('Y/m/d')));
$numberDays = intval($timeDiff / 86400);
// if order is not older than 365 days return didDontate with true
if ($numberDays <= '365') {
foreach ($previousOrder->getLineItems() as $lineItem) {
$purchable = $lineItem->getPurchasable();
if ($purchable && $purchable instanceof \craft\commerce\elements\Variant && $purchable->getProduct()->getType()->handle == 'donation' && $purchable->getPrice() >= '75' && $purchable) {
$didDonate = true;
}
}
}
}
return $didDonate;
}
/**
* Apply dicount if customer donated
*/
public function adjust(Order $order): array
{
// get the current cart
$cart = Plugin::getInstance()->getCart();
// check if a donation is in current cart or in a previous order
if ($this->checkIfInCart($order) == true || $this->checkIfDonated($order) == true) {
// get lineitems from cart to apply discount on
foreach ($cart->getLineItems() as $lineItem) {
$purchable = $lineItem->getPurchasable();
$quantity = $lineItem->qty;
// check if lineitems belong to the productype shop
if ($purchable && $purchable instanceof \craft\commerce\elements\Variant && $purchable->getProduct()->getType()->handle == 'shop') {
// apply discount
$purchablePrice = $purchable->getPrice();
$discountValues[] = $purchablePrice * 0.4 * $quantity;
}
}
// sum up all dicountValues
$totalDiscount = array_sum($discountValues);
// set new OrderAdjustment $friendAdjuster
$friendsDiscountAdjuster = new OrderAdjustment();
$friendsDiscountAdjuster->type = "Freundesrabatt";
$friendsDiscountAdjuster->name = "40% Freundesrabatt";
$friendsDiscountAdjuster->amount = -$totalDiscount;
$friendsDiscountAdjuster->description = $friendsDiscountAdjuster->amount;
$friendsDiscountAdjuster->orderId = $order->id;
$friendsDiscountAdjuster->included = false;
return [$friendsDiscountAdjuster];
}
return [];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment