I need add coupon code from $100 to newsletter. I did rewrite \Magento\Newsletter\Model\Subscriber in the method sendConfirmationSuccessEmail
->setTemplateVars(
['subscriber' => $this,
'coupon_code' => $this->getCouponCode()
])
protected function getCouponCode() {
. . .
. . .
return $couponCode;
}
How automatically generate coupon code in magento 2?
Have you defined a Shopping Cart Price Rule? If not, that's where to start. In the admin area, go to Promotions > Shopping Cart Price Rules > Add New Rule, and define a Specific Coupon with Use Auto Generation selected.
Once you have defined the rule for whatever specific discount you wish to offer, save the rule and make a note of the rule ID from the the Shopping Cart Price Rules row showing the rule you just created.
Then add something like the following, using the rule ID of the rule you just created:
The function below takes an associative array with the following options:
rule_id = the rule ID, from above
qty = number of coupon codes to instruct Magento to generate
length = length of each generated coupon code
format = alphanum (for alphanumeric codes) OR alpha (for alphabetical codes) OR num (for numeric codes)
protected function getCouponCode($couponData)
{
$rule = $this->_loadSalesRule($ruleId);
// Reference the MassGenerator on this rule.
/** #var Mage_SalesRule_Model_Coupon_Massgenerator $generator */
$generator = $rule->getCouponMassGenerator();
// Validate the generator
if (!$generator->validateData($couponData)) {
$this->_critical(Mage::helper('salesrule')->__('Coupon AutoGen API: Invalid parameters passed in.'),
Mage_Api2_Model_Server::HTTP_BAD_REQUEST);
} else {
// Set the data for the generator
$generator->setData($couponData);
// Generate a pool of coupon codes for the Generate Coupons rule
$generator->generatePool();
}
}
Related
I have seen this question come up here and there, but it has not been fully answered. I know how to get the WC_Order_Item_Shipping information from an order, but how can I get a WC_Shipping_Method object from the orders shipping method item?
I have stored some custom options through a custom field in the admin setting page for the WooCommerce shipping methods. I want to get this field from an order. Right now I am doing this, and I can get to my information:
foreach ($order->get_shipping_methods() as $shipping_method) {
$options = get_option('woocommerce_' . $shipping_method->get_method_id() . '_' . $shipping_method->get_instance_id() . '_settings');
}
But this does not feel future proof. If the structure of the saved data changes, then everything will break. I'd rather use the getter from WC_Shipping_Method get_instance_option(). The problem is that I am not allowed to instantiate such an object, and there does not seem to be a wc_get_shipping_method() function I can use to get the method based on it's instance ID, such as with orders and products.
I could go the long route and save this info to order meta after payment is made, but that also does not seem like an optimized way of doing it. I want to get the information as it is saved in the present moment, not as it was saved to an order when the order was made.
Is the way that I am doing it now the only way, or is there a better way?
EDIT:
This is the code that adds the custom field:
function shipping_instance_form_add_extra_fields($settings)
{
$settings['custom_shipping_id'] = [
'title' => 'Custom Shipping ID',
'type' => 'number',
'description' => '',
];
return $settings;
}
function shipping_instance_form_fields_filters()
{
$shipping_methods = WC()->shipping->get_shipping_methods();
foreach ($shipping_methods as $shipping_method) {
add_filter('woocommerce_shipping_instance_form_fields_' . $shipping_method->id, 'shipping_instance_form_add_extra_fields');
}
}
add_action('woocommerce_init', 'shipping_instance_form_fields_filters');
If you already have shipping method instance id you can simply create instance of class WC_Shipping_Method giving it instance id as constructor parameter like $method = new WC_Shipping_Method($instance_id). After that you can use method get_instance_option to get value of that option like $custom_shipping_id = $method->get_instance_option('custom_shipping_id');
i am trying to use Promotion code instead of coupon code in laravel cashier/stripe official package but i couldn't find any help in there on how to apply promotion code instead of coupon on subscription as i know how to apply coupon but i want to apply promotion code, how can i do it.
below is my code for applying coupon when creating new subscription but i don't know how can i achieve it using promotion code:
$subscription = $user->newSubscription($plan->name, $selectedPlan);
// Add the trial days if any
if ($plan->trial_days) {
$subscription = $subscription->trialDays($plan->trial_days);
}
// Add the coupon id if any
if ($request->input('coupon_id')) {
$subscription = $subscription->withCoupon($request->input('coupon_id'));
}
$subscription->create($paymentMethod->id, [
'email' => $user->email
]);
You can add promotion code by using the ->withPromotionCode() e.g.
if ($request->input('promotion_code_id')) {
$subscription = $subscription->withPromotionCode($request->input('promotion_code_id'));
}
However, this function requires the promotion code ID instead of the code, and most likely you want your user to key in the code, not the ID. In such case, you can retrieve all active promotion codes and match the code.
if ($request->has('promotion_code')) {
$stripeClient = new \Stripe\StripeClient(config('cashier.secret'));
$result = $this->stripe->promotionCodes->all(
['code' => $request->get("promotion_code"), 'active' => true]
);
if($result->isEmpty()){
// handle invalid promo code here
}
$promoCodeID = $result->first()->id;
$subscription = $subscription->withPromotionCode($promoCodeID);
}
In the CartRule class of Prestashop, are defined this constants:
/* Filters used when retrieving the cart rules applied to a cart of when calculating the value of a reduction */
const FILTER_ACTION_ALL = 1;
const FILTER_ACTION_SHIPPING = 2;
const FILTER_ACTION_REDUCTION = 3;
const FILTER_ACTION_GIFT = 4;
const FILTER_ACTION_ALL_NOCAP = 5;
Does anyone know what cart rules are filtered when using FILTER_ACTION_ALL_NOCAP?
Thank you.
It's used for cart rules with partial use. When you call function getContextualValue() from CartRule class with CartRule::FILTER_ACTION_ALL_NOCAP filter, it returns the total cart rule amount, not only the amount that should be applied in the current cart (amount can never be higher than products amount):
// The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation)
if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) {
$reduction_amount = min($reduction_amount, $this->reduction_tax ? $cart_amount_ti : $cart_amount_te);
}
When the order is validated, the cart rule value is retrieved:
$values = array(
'tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package),
'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package)
);
And a new cart rule is generated if necessary.
Whenever you load the cart page in Magento, the following code is run
$cart->init();
$cart->save();
One side effect of this is that the prices for any items in the cart are updated if the price of the product has been updated. This actually updates the entry in sales_flat_quote_item. I'm trying to track down where in code the price is updated on each quote item, and where each quote item is saved.
I know the myrid locations it could be set. I'm hoping someone knows where it actually is set. Magento 1.7x branch specifically, although info from all versions is welcome.
Dug this one up myself. So there's this
#File: app/code/core/Mage/Sales/Model/Quote.php
foreach ($this->getAllAddresses() as $address) {
...
$address->collectTotals();
...
}
which leads to this
#File: app/code/core/Mage/Sales/Model/Quote/Address.php
public function collectTotals()
{
Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_before', array($this->_eventObject => $this));
foreach ($this->getTotalCollector()->getCollectors() as $model) {
$model->collect($this);
}
Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_after', array($this->_eventObject => $this));
return $this;
}
The getTotalCollector object returns a sales/quote_address_total_collector object, which loads a series of collector models from global/sales/quote/totals and calls collect on them. The sub-total collector's collect method ultimately calls this
#File: app/code/core/Mage/Sales/Model/Quote/Address/Total/Subtotal.php
protected function _initItem($address, $item)
{
//...
if ($quoteItem->getParentItem() && $quoteItem->isChildrenCalculated()) {
$finalPrice = $quoteItem->getParentItem()->getProduct()->getPriceModel()->getChildFinalPrice(
$quoteItem->getParentItem()->getProduct(),
$quoteItem->getParentItem()->getQty(),
$quoteItem->getProduct(),
$quoteItem->getQty()
);
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
$item->calcRowTotal();
} else if (!$quoteItem->getParentItem()) {
$finalPrice = $product->getFinalPrice($quoteItem->getQty());
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
$item->calcRowTotal();
$this->_addAmount($item->getRowTotal());
$this->_addBaseAmount($item->getBaseRowTotal());
$address->setTotalQty($address->getTotalQty() + $item->getQty());
}
//...
}
and this is where the quote item gets it's price set/rest.
From a high level, the code that starts the whole process are lines 464 and 465 of Mage_Checkout_Model_Cart :
$this->getQuote()->collectTotals();
$this->getQuote()->save();
The new product price is being set against the quote in Mage_Sales_Model_Quote_Address_Total_Subtotal in the _initItem method. You will see $item->setPrice in the the if / else statement starting at line 104
If you are trying to do custom price changes on products in the cart, rather than extend and modify core classes, I use an observer sales_quote_save_before. It works great if you are trying to customize pricing (especially when I have products that can be custom length).
I'd like to create a shopping cart price rule that gives a user 10% off their order when and if they complete a process on my Magento site.
There's a method here that inserts the rule directly to the database. That's a bit invasive for my tastes.
How would I go about this using Magento methods?
As a general principle, you should be able to do anything that the Magento system itself does without writing a single line of SQL. Almost all the Magento data structures use Magento Model classes.
Run the following code somewhere to see what a salesrule/rule model looks like. This assumes you've created a single Shopping Cart Price Rule in the admin with an ID of 1
$coupon = Mage::getModel('salesrule/rule')->load(1);
var_dump($coupon->getData());
Using the dumped data as a guide, we can programatically create a model using the following
$coupon = Mage::getModel('salesrule/rule');
$coupon->setName('test coupon')
->setDescription('this is a description')
->setFromDate('2010-05-09')
->setCouponCode('CODENAME')
->setUsesPerCoupon(1)
->setUsesPerCustomer(1)
->setCustomerGroupIds(array(1)) //an array of customer grou pids
->setIsActive(1)
//serialized conditions. the following examples are empty
->setConditionsSerialized('a:6:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";}')
->setActionsSerialized('a:6:{s:4:"type";s:40:"salesrule/rule_condition_product_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";}')
->setStopRulesProcessing(0)
->setIsAdvanced(1)
->setProductIds('')
->setSortOrder(0)
->setSimpleAction('by_percent')
->setDiscountAmount(10)
->setDiscountQty(null)
->setDiscountStep('0')
->setSimpleFreeShipping('0')
->setApplyToShipping('0')
->setIsRss(0)
->setWebsiteIds(array(1));
$coupon->save();
For anyone that's curious, the above is generated code, using the technique discussed here
Have a look at my code.It will add Action condition.
$coupon_rule = Mage::getModel('salesrule/rule');
$coupon_rule->setName($c_data[1])
->setDescription($c_data[2])
->setFromDate($fromDate)
->setToDate($toDate)
->setUsesPerCustomer(0)
->setCustomerGroupIds(array(0,1,2,3)) //an array of customer grou pids
->setIsActive(1)
->setCouponType(2)
->setCouponCode($c_data[0])
->setUsesPerCoupon(1)
//serialized conditions. the following examples are empty
->setConditionsSerialized('')
->setActionsSerialized('')
->setStopRulesProcessing(0)
->setIsAdvanced(1)
->setProductIds('')
->setSortOrder(0)
->setSimpleAction('by_percent')
->setDiscountAmount($c_data[5])
->setDiscountQty(1)
->setDiscountStep('0')
->setSimpleFreeShipping('0')
->setApplyToShipping('1')
->setIsRss(1)
->setWebsiteIds(explode(',',$c_data[6]));
$sku =$c_data[7]; // Put your product SKU here
$skuCond = Mage::getModel('salesrule/rule_condition_product')
->setType('salesrule/rule_condition_product')
->setAttribute('sku')
->setOperator('==')
->setValue($sku);
$coupon_rule->getActions()->addCondition($skuCond);
$coupon_rule->save();
echo "New Coupon was added and its ID is ".$coupon_rule->getId().'<br/>';<br/>
If you want to add Condition for shopping cart price rule then follow this example.
$sku =$c_data[7]; // Put your product SKU here
$found = Mage::getModel('salesrule/rule_condition_product_found')
->setType('salesrule/rule_condition_product_found')
->setValue(1) // 1 == FOUND
->setAggregator('all'); // match ALL conditions
$coupon_rule->getConditions()->addCondition($found);
$skuCond = Mage::getModel('salesrule/rule_condition_product')
->setType('salesrule/rule_condition_product')
->setAttribute('sku')
->setOperator('==')
->setValue($sku);
$found->addCondition($skuCond);
$coupon_rule->save();