Version Notes
- Fix encoding issue with french translations
- Add more translation
Download this release
Release Info
| Developer | Digital Pianism |
| Extension | DigitalPianism_Abandonedcarts |
| Version | 0.3.2 |
| Comparing to | |
| See all releases | |
Code changes from version 0.3.1 to 0.3.2
- app/code/community/DigitalPianism/Abandonedcarts/Model/Observer.php +54 -51
- app/code/community/DigitalPianism/Abandonedcarts/etc/config.xml +1 -1
- app/code/community/DigitalPianism/Abandonedcarts/etc/system.xml +1 -1
- app/locale/en_US/DigitalPianism_Abandonedcarts.csv +2 -1
- app/locale/fr_FR/DigitalPianism_Abandonedcarts.csv +14 -13
- package.xml +6 -5
app/code/community/DigitalPianism/Abandonedcarts/Model/Observer.php
CHANGED
|
@@ -17,7 +17,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 17 |
$store = Mage_Core_Model_App::ADMIN_STORE_ID;
|
| 18 |
$timezone = Mage::app()->getStore($store)->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
|
| 19 |
date_default_timezone_set($timezone);
|
| 20 |
-
|
| 21 |
// Current date
|
| 22 |
$currentdate = date("Ymd");
|
| 23 |
|
|
@@ -26,7 +26,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 26 |
$year = (int)substr($currentdate,0,4);
|
| 27 |
|
| 28 |
$date = array('year' => $year,'month' => $month,'day' => $day,'hour' => 23,'minute' => 59,'second' => 59);
|
| 29 |
-
|
| 30 |
$today = new Zend_Date($date);
|
| 31 |
$today->setTimeZone("UTC");
|
| 32 |
|
|
@@ -73,14 +73,14 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 73 |
// Test if the customer is already in the array
|
| 74 |
if (!array_key_exists($args['row']['customer_email'], $this->_recipients))
|
| 75 |
{
|
| 76 |
-
// Create an array of variables to assign to template
|
| 77 |
-
$emailTemplateVariables = array();
|
| 78 |
-
|
| 79 |
// Array that contains the data which will be used inside the template
|
| 80 |
-
$emailTemplateVariables['fullname'] = $args['row']['customer_firstname'].' '.$args['row']['customer_lastname'];
|
| 81 |
$emailTemplateVariables['firstname'] = $args['row']['customer_firstname'];
|
| 82 |
$emailTemplateVariables['productname'] = $args['row']['product_name'];
|
| 83 |
-
|
| 84 |
// Assign the values to the array of recipients
|
| 85 |
$this->_recipients[$args['row']['customer_email']]['cartId'] = $args['row']['cart_id'];
|
| 86 |
|
|
@@ -95,7 +95,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 95 |
|
| 96 |
// Add product image
|
| 97 |
$emailTemplateVariables['productimage'] = (string)Mage::helper('catalog/image')->init($_productCollection->getFirstItem(), 'image');
|
| 98 |
-
|
| 99 |
$emailTemplateVariables['extraproductcount'] = 0;
|
| 100 |
}
|
| 101 |
else
|
|
@@ -127,36 +127,36 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 127 |
$fromDate = $this->_getToday();
|
| 128 |
}
|
| 129 |
else $fromDate = $args['row']['product_special_from_date'];
|
| 130 |
-
|
| 131 |
// Do the same for the special to date
|
| 132 |
if (!array_key_exists('product_special_to_date',$args['row']) || !$args['row']['product_special_to_date'])
|
| 133 |
{
|
| 134 |
$toDate = $this->_getToday();
|
| 135 |
}
|
| 136 |
else $toDate = $args['row']['product_special_to_date'];
|
| 137 |
-
|
| 138 |
// We need to ensure that the price in cart is higher than the new special price
|
| 139 |
// As well as the date comparison in case the sale is over or hasn't started
|
| 140 |
-
if ($args['row']['product_price_in_cart'] > 0.00
|
| 141 |
-
&& $args['row']['product_special_price'] > 0.00
|
| 142 |
&& ($args['row']['product_price_in_cart'] > $args['row']['product_special_price'])
|
| 143 |
&& ($fromDate <= $this->_getToday())
|
| 144 |
&& ($toDate >= $this->_getToday()))
|
| 145 |
{
|
| 146 |
-
|
| 147 |
// Test if the customer is already in the array
|
| 148 |
if (!array_key_exists($args['row']['customer_email'], $this->_saleRecipients))
|
| 149 |
{
|
| 150 |
-
// Create an array of variables to assign to template
|
| 151 |
-
$emailTemplateVariables = array();
|
| 152 |
-
|
| 153 |
// Array that contains the data which will be used inside the template
|
| 154 |
-
$emailTemplateVariables['fullname'] = $args['row']['customer_firstname'].' '.$args['row']['customer_lastname'];
|
| 155 |
$emailTemplateVariables['firstname'] = $args['row']['customer_firstname'];
|
| 156 |
-
$emailTemplateVariables['productname'] = $args['row']['product_name'];
|
| 157 |
-
$emailTemplateVariables['cartprice'] = number_format($args['row']['product_price_in_cart'],2);
|
| 158 |
$emailTemplateVariables['specialprice'] = number_format($args['row']['product_special_price'],2);
|
| 159 |
-
|
| 160 |
// Assign the values to the array of recipients
|
| 161 |
$this->_saleRecipients[$args['row']['customer_email']]['cartId'] = $args['row']['cart_id'];
|
| 162 |
|
|
@@ -192,7 +192,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 192 |
}
|
| 193 |
$emailTemplateVariables['extraproductcount'] += 1;
|
| 194 |
}
|
| 195 |
-
|
| 196 |
// Add currency codes to prices
|
| 197 |
$emailTemplateVariables['cartprice'] = Mage::helper('core')->currency($emailTemplateVariables['cartprice'], true, false);
|
| 198 |
$emailTemplateVariables['specialprice'] = Mage::helper('core')->currency($emailTemplateVariables['specialprice'], true, false);
|
|
@@ -200,7 +200,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 200 |
{
|
| 201 |
$emailTemplateVariables['discount'] = Mage::helper('core')->currency($emailTemplateVariables['discount'], true, false);
|
| 202 |
}
|
| 203 |
-
|
| 204 |
// Assign the array of template variables
|
| 205 |
$this->_saleRecipients[$args['row']['customer_email']]['emailTemplateVariables'] = $emailTemplateVariables;
|
| 206 |
}
|
|
@@ -213,14 +213,14 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 213 |
protected function _sendSaleEmails($dryrun,$testemail)
|
| 214 |
{
|
| 215 |
try
|
| 216 |
-
{
|
| 217 |
// Get the transactional email template
|
| 218 |
$templateId = Mage::getStoreConfig('abandonedcartsconfig/options/email_template_sale');
|
| 219 |
// Get the sender
|
| 220 |
$sender = array();
|
| 221 |
$sender['email'] = Mage::getStoreConfig('abandonedcartsconfig/options/email');
|
| 222 |
$sender['name'] = Mage::getStoreConfig('abandonedcartsconfig/options/name');
|
| 223 |
-
|
| 224 |
// Send the emails via a loop
|
| 225 |
foreach ($this->_getSaleRecipients() as $email => $recipient)
|
| 226 |
{
|
|
@@ -248,7 +248,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 248 |
else
|
| 249 |
{
|
| 250 |
Mage::helper('abandonedcarts')->log(__METHOD__ . "sendAbandonedCartsSaleEmail: " . $email);
|
| 251 |
-
|
| 252 |
// Send the email
|
| 253 |
Mage::getModel('core/email_template')
|
| 254 |
->sendTransactional(
|
|
@@ -259,13 +259,13 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 259 |
$recipient['emailTemplateVariables'],
|
| 260 |
null);
|
| 261 |
}
|
| 262 |
-
|
| 263 |
// Load the quote
|
| 264 |
$quote = Mage::getModel('sales/quote')->load($recipient['cartId']);
|
| 265 |
|
| 266 |
// We change the notification attribute
|
| 267 |
$quote->setAbandonedSaleNotified(1);
|
| 268 |
-
|
| 269 |
// Save only if dryrun is false or if the test email is set and found
|
| 270 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
| 271 |
{
|
|
@@ -286,14 +286,14 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 286 |
protected function _sendEmails($dryrun,$testemail)
|
| 287 |
{
|
| 288 |
try
|
| 289 |
-
{
|
| 290 |
// Get the transactional email template
|
| 291 |
$templateId = Mage::getStoreConfig('abandonedcartsconfig/options/email_template');
|
| 292 |
// Get the sender
|
| 293 |
$sender = array();
|
| 294 |
$sender['email'] = Mage::getStoreConfig('abandonedcartsconfig/options/email');
|
| 295 |
$sender['name'] = Mage::getStoreConfig('abandonedcartsconfig/options/name');
|
| 296 |
-
|
| 297 |
// Send the emails via a loop
|
| 298 |
foreach ($this->_getRecipients() as $email => $recipient)
|
| 299 |
{
|
|
@@ -357,7 +357,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 357 |
* @param boolean $dryrun if dryrun is set to true, it won't send emails and won't alter quotes
|
| 358 |
* @param string $testemail email to test
|
| 359 |
*/
|
| 360 |
-
public function sendAbandonedCartsSaleEmail($dryrun = false, $testemail = null)
|
| 361 |
{
|
| 362 |
try
|
| 363 |
{
|
|
@@ -369,7 +369,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 369 |
if (Mage::helper('abandonedcarts')->isSaleEnabled())
|
| 370 |
{
|
| 371 |
$this->_setToday();
|
| 372 |
-
|
| 373 |
// Get the attribute id for the status attribute
|
| 374 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
| 375 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
|
@@ -378,7 +378,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 378 |
$spriceId = $eavAttribute->getIdByCode('catalog_product', 'special_price');
|
| 379 |
$spfromId = $eavAttribute->getIdByCode('catalog_product', 'special_from_date');
|
| 380 |
$sptoId = $eavAttribute->getIdByCode('catalog_product', 'special_to_date');
|
| 381 |
-
|
| 382 |
// Loop through the stores
|
| 383 |
foreach (Mage::app()->getWebsites() as $website) {
|
| 384 |
// Get the website id
|
|
@@ -386,22 +386,22 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 386 |
foreach ($website->getGroups() as $group) {
|
| 387 |
$stores = $group->getStores();
|
| 388 |
foreach ($stores as $store) {
|
| 389 |
-
|
| 390 |
// Get the store id
|
| 391 |
$storeId = $store->getStoreId();
|
| 392 |
-
|
| 393 |
// Init the store to be able to load the quote and the collections properly
|
| 394 |
Mage::app()->init($storeId,'store');
|
| 395 |
-
|
| 396 |
// Get the product collection
|
| 397 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
| 398 |
-
|
| 399 |
// Database TableNams
|
| 400 |
$eavEntityType = Mage::getSingleton("core/resource")->getTableName('eav_entity_type');
|
| 401 |
$eavAttribute = Mage::getSingleton("core/resource")->getTableName('eav_attribute');
|
| 402 |
-
|
| 403 |
// If flat catalog is enabled
|
| 404 |
-
if (Mage::helper('catalog/product_flat')->isEnabled())
|
| 405 |
{
|
| 406 |
// First collection: carts with products that became on sale
|
| 407 |
// Join the collection with the required tables
|
|
@@ -512,13 +512,13 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 512 |
null)
|
| 513 |
->order('quote_table.updated_at DESC');
|
| 514 |
}
|
| 515 |
-
|
| 516 |
//$collection->printlogquery(true,true);
|
| 517 |
$collection->load();
|
| 518 |
-
|
| 519 |
// Skip the rest of the code if the collection is empty
|
| 520 |
if ($collection->getSize() == 0) continue;
|
| 521 |
-
|
| 522 |
// Call iterator walk method with collection query string and callback method as parameters
|
| 523 |
// Has to be used to handle massive collection instead of foreach
|
| 524 |
Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array(array($this, 'generateSaleRecipients')));
|
|
@@ -553,11 +553,11 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 553 |
{
|
| 554 |
if (Mage::helper('abandonedcarts')->isEnabled())
|
| 555 |
{
|
| 556 |
-
// Date handling
|
| 557 |
$store = Mage_Core_Model_App::ADMIN_STORE_ID;
|
| 558 |
$timezone = Mage::app()->getStore($store)->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
|
| 559 |
date_default_timezone_set($timezone);
|
| 560 |
-
|
| 561 |
// If the nodate parameter is set to false
|
| 562 |
if (!$nodate)
|
| 563 |
{
|
|
@@ -570,13 +570,13 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 570 |
// We create a date in the future to handle all abandoned carts
|
| 571 |
$delay = date('Y-m-d H:i:s', strtotime("+7 day"));
|
| 572 |
}
|
| 573 |
-
|
| 574 |
// Get the attribute id for several attributes
|
| 575 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
| 576 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
| 577 |
$nameId = $eavAttribute->getIdByCode('catalog_product', 'name');
|
| 578 |
$priceId = $eavAttribute->getIdByCode('catalog_product', 'price');
|
| 579 |
-
|
| 580 |
// Loop through the stores
|
| 581 |
foreach (Mage::app()->getWebsites() as $website) {
|
| 582 |
// Get the website id
|
|
@@ -584,17 +584,17 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 584 |
foreach ($website->getGroups() as $group) {
|
| 585 |
$stores = $group->getStores();
|
| 586 |
foreach ($stores as $store) {
|
| 587 |
-
|
| 588 |
// Get the store id
|
| 589 |
$storeId = $store->getStoreId();
|
| 590 |
// Init the store to be able to load the quote and the collections properly
|
| 591 |
Mage::app()->init($storeId,'store');
|
| 592 |
-
|
| 593 |
// Get the product collection
|
| 594 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
| 595 |
-
|
| 596 |
// If flat catalog is enabled
|
| 597 |
-
if (Mage::helper('catalog/product_flat')->isEnabled())
|
| 598 |
{
|
| 599 |
// First collection: carts with products that became on sale
|
| 600 |
// Join the collection with the required tables
|
|
@@ -682,10 +682,13 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
| 682 |
null)
|
| 683 |
->order('quote_table.updated_at DESC');
|
| 684 |
}
|
| 685 |
-
|
| 686 |
//$collection->printlogquery(true,true);
|
| 687 |
$collection->load();
|
| 688 |
-
|
|
|
|
|
|
|
|
|
|
| 689 |
// Call iterator walk method with collection query string and callback method as parameters
|
| 690 |
// Has to be used to handle massive collection instead of foreach
|
| 691 |
Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array(array($this, 'generateRecipients')));
|
| 17 |
$store = Mage_Core_Model_App::ADMIN_STORE_ID;
|
| 18 |
$timezone = Mage::app()->getStore($store)->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
|
| 19 |
date_default_timezone_set($timezone);
|
| 20 |
+
|
| 21 |
// Current date
|
| 22 |
$currentdate = date("Ymd");
|
| 23 |
|
| 26 |
$year = (int)substr($currentdate,0,4);
|
| 27 |
|
| 28 |
$date = array('year' => $year,'month' => $month,'day' => $day,'hour' => 23,'minute' => 59,'second' => 59);
|
| 29 |
+
|
| 30 |
$today = new Zend_Date($date);
|
| 31 |
$today->setTimeZone("UTC");
|
| 32 |
|
| 73 |
// Test if the customer is already in the array
|
| 74 |
if (!array_key_exists($args['row']['customer_email'], $this->_recipients))
|
| 75 |
{
|
| 76 |
+
// Create an array of variables to assign to template
|
| 77 |
+
$emailTemplateVariables = array();
|
| 78 |
+
|
| 79 |
// Array that contains the data which will be used inside the template
|
| 80 |
+
$emailTemplateVariables['fullname'] = $args['row']['customer_firstname'].' '.$args['row']['customer_lastname'];
|
| 81 |
$emailTemplateVariables['firstname'] = $args['row']['customer_firstname'];
|
| 82 |
$emailTemplateVariables['productname'] = $args['row']['product_name'];
|
| 83 |
+
|
| 84 |
// Assign the values to the array of recipients
|
| 85 |
$this->_recipients[$args['row']['customer_email']]['cartId'] = $args['row']['cart_id'];
|
| 86 |
|
| 95 |
|
| 96 |
// Add product image
|
| 97 |
$emailTemplateVariables['productimage'] = (string)Mage::helper('catalog/image')->init($_productCollection->getFirstItem(), 'image');
|
| 98 |
+
|
| 99 |
$emailTemplateVariables['extraproductcount'] = 0;
|
| 100 |
}
|
| 101 |
else
|
| 127 |
$fromDate = $this->_getToday();
|
| 128 |
}
|
| 129 |
else $fromDate = $args['row']['product_special_from_date'];
|
| 130 |
+
|
| 131 |
// Do the same for the special to date
|
| 132 |
if (!array_key_exists('product_special_to_date',$args['row']) || !$args['row']['product_special_to_date'])
|
| 133 |
{
|
| 134 |
$toDate = $this->_getToday();
|
| 135 |
}
|
| 136 |
else $toDate = $args['row']['product_special_to_date'];
|
| 137 |
+
|
| 138 |
// We need to ensure that the price in cart is higher than the new special price
|
| 139 |
// As well as the date comparison in case the sale is over or hasn't started
|
| 140 |
+
if ($args['row']['product_price_in_cart'] > 0.00
|
| 141 |
+
&& $args['row']['product_special_price'] > 0.00
|
| 142 |
&& ($args['row']['product_price_in_cart'] > $args['row']['product_special_price'])
|
| 143 |
&& ($fromDate <= $this->_getToday())
|
| 144 |
&& ($toDate >= $this->_getToday()))
|
| 145 |
{
|
| 146 |
+
|
| 147 |
// Test if the customer is already in the array
|
| 148 |
if (!array_key_exists($args['row']['customer_email'], $this->_saleRecipients))
|
| 149 |
{
|
| 150 |
+
// Create an array of variables to assign to template
|
| 151 |
+
$emailTemplateVariables = array();
|
| 152 |
+
|
| 153 |
// Array that contains the data which will be used inside the template
|
| 154 |
+
$emailTemplateVariables['fullname'] = $args['row']['customer_firstname'].' '.$args['row']['customer_lastname'];
|
| 155 |
$emailTemplateVariables['firstname'] = $args['row']['customer_firstname'];
|
| 156 |
+
$emailTemplateVariables['productname'] = $args['row']['product_name'];
|
| 157 |
+
$emailTemplateVariables['cartprice'] = number_format($args['row']['product_price_in_cart'],2);
|
| 158 |
$emailTemplateVariables['specialprice'] = number_format($args['row']['product_special_price'],2);
|
| 159 |
+
|
| 160 |
// Assign the values to the array of recipients
|
| 161 |
$this->_saleRecipients[$args['row']['customer_email']]['cartId'] = $args['row']['cart_id'];
|
| 162 |
|
| 192 |
}
|
| 193 |
$emailTemplateVariables['extraproductcount'] += 1;
|
| 194 |
}
|
| 195 |
+
|
| 196 |
// Add currency codes to prices
|
| 197 |
$emailTemplateVariables['cartprice'] = Mage::helper('core')->currency($emailTemplateVariables['cartprice'], true, false);
|
| 198 |
$emailTemplateVariables['specialprice'] = Mage::helper('core')->currency($emailTemplateVariables['specialprice'], true, false);
|
| 200 |
{
|
| 201 |
$emailTemplateVariables['discount'] = Mage::helper('core')->currency($emailTemplateVariables['discount'], true, false);
|
| 202 |
}
|
| 203 |
+
|
| 204 |
// Assign the array of template variables
|
| 205 |
$this->_saleRecipients[$args['row']['customer_email']]['emailTemplateVariables'] = $emailTemplateVariables;
|
| 206 |
}
|
| 213 |
protected function _sendSaleEmails($dryrun,$testemail)
|
| 214 |
{
|
| 215 |
try
|
| 216 |
+
{
|
| 217 |
// Get the transactional email template
|
| 218 |
$templateId = Mage::getStoreConfig('abandonedcartsconfig/options/email_template_sale');
|
| 219 |
// Get the sender
|
| 220 |
$sender = array();
|
| 221 |
$sender['email'] = Mage::getStoreConfig('abandonedcartsconfig/options/email');
|
| 222 |
$sender['name'] = Mage::getStoreConfig('abandonedcartsconfig/options/name');
|
| 223 |
+
|
| 224 |
// Send the emails via a loop
|
| 225 |
foreach ($this->_getSaleRecipients() as $email => $recipient)
|
| 226 |
{
|
| 248 |
else
|
| 249 |
{
|
| 250 |
Mage::helper('abandonedcarts')->log(__METHOD__ . "sendAbandonedCartsSaleEmail: " . $email);
|
| 251 |
+
|
| 252 |
// Send the email
|
| 253 |
Mage::getModel('core/email_template')
|
| 254 |
->sendTransactional(
|
| 259 |
$recipient['emailTemplateVariables'],
|
| 260 |
null);
|
| 261 |
}
|
| 262 |
+
|
| 263 |
// Load the quote
|
| 264 |
$quote = Mage::getModel('sales/quote')->load($recipient['cartId']);
|
| 265 |
|
| 266 |
// We change the notification attribute
|
| 267 |
$quote->setAbandonedSaleNotified(1);
|
| 268 |
+
|
| 269 |
// Save only if dryrun is false or if the test email is set and found
|
| 270 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
| 271 |
{
|
| 286 |
protected function _sendEmails($dryrun,$testemail)
|
| 287 |
{
|
| 288 |
try
|
| 289 |
+
{
|
| 290 |
// Get the transactional email template
|
| 291 |
$templateId = Mage::getStoreConfig('abandonedcartsconfig/options/email_template');
|
| 292 |
// Get the sender
|
| 293 |
$sender = array();
|
| 294 |
$sender['email'] = Mage::getStoreConfig('abandonedcartsconfig/options/email');
|
| 295 |
$sender['name'] = Mage::getStoreConfig('abandonedcartsconfig/options/name');
|
| 296 |
+
|
| 297 |
// Send the emails via a loop
|
| 298 |
foreach ($this->_getRecipients() as $email => $recipient)
|
| 299 |
{
|
| 357 |
* @param boolean $dryrun if dryrun is set to true, it won't send emails and won't alter quotes
|
| 358 |
* @param string $testemail email to test
|
| 359 |
*/
|
| 360 |
+
public function sendAbandonedCartsSaleEmail($dryrun = false, $testemail = null)
|
| 361 |
{
|
| 362 |
try
|
| 363 |
{
|
| 369 |
if (Mage::helper('abandonedcarts')->isSaleEnabled())
|
| 370 |
{
|
| 371 |
$this->_setToday();
|
| 372 |
+
|
| 373 |
// Get the attribute id for the status attribute
|
| 374 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
| 375 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
| 378 |
$spriceId = $eavAttribute->getIdByCode('catalog_product', 'special_price');
|
| 379 |
$spfromId = $eavAttribute->getIdByCode('catalog_product', 'special_from_date');
|
| 380 |
$sptoId = $eavAttribute->getIdByCode('catalog_product', 'special_to_date');
|
| 381 |
+
|
| 382 |
// Loop through the stores
|
| 383 |
foreach (Mage::app()->getWebsites() as $website) {
|
| 384 |
// Get the website id
|
| 386 |
foreach ($website->getGroups() as $group) {
|
| 387 |
$stores = $group->getStores();
|
| 388 |
foreach ($stores as $store) {
|
| 389 |
+
|
| 390 |
// Get the store id
|
| 391 |
$storeId = $store->getStoreId();
|
| 392 |
+
|
| 393 |
// Init the store to be able to load the quote and the collections properly
|
| 394 |
Mage::app()->init($storeId,'store');
|
| 395 |
+
|
| 396 |
// Get the product collection
|
| 397 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
| 398 |
+
|
| 399 |
// Database TableNams
|
| 400 |
$eavEntityType = Mage::getSingleton("core/resource")->getTableName('eav_entity_type');
|
| 401 |
$eavAttribute = Mage::getSingleton("core/resource")->getTableName('eav_attribute');
|
| 402 |
+
|
| 403 |
// If flat catalog is enabled
|
| 404 |
+
if (Mage::helper('catalog/product_flat')->isEnabled())
|
| 405 |
{
|
| 406 |
// First collection: carts with products that became on sale
|
| 407 |
// Join the collection with the required tables
|
| 512 |
null)
|
| 513 |
->order('quote_table.updated_at DESC');
|
| 514 |
}
|
| 515 |
+
|
| 516 |
//$collection->printlogquery(true,true);
|
| 517 |
$collection->load();
|
| 518 |
+
|
| 519 |
// Skip the rest of the code if the collection is empty
|
| 520 |
if ($collection->getSize() == 0) continue;
|
| 521 |
+
|
| 522 |
// Call iterator walk method with collection query string and callback method as parameters
|
| 523 |
// Has to be used to handle massive collection instead of foreach
|
| 524 |
Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array(array($this, 'generateSaleRecipients')));
|
| 553 |
{
|
| 554 |
if (Mage::helper('abandonedcarts')->isEnabled())
|
| 555 |
{
|
| 556 |
+
// Date handling
|
| 557 |
$store = Mage_Core_Model_App::ADMIN_STORE_ID;
|
| 558 |
$timezone = Mage::app()->getStore($store)->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
|
| 559 |
date_default_timezone_set($timezone);
|
| 560 |
+
|
| 561 |
// If the nodate parameter is set to false
|
| 562 |
if (!$nodate)
|
| 563 |
{
|
| 570 |
// We create a date in the future to handle all abandoned carts
|
| 571 |
$delay = date('Y-m-d H:i:s', strtotime("+7 day"));
|
| 572 |
}
|
| 573 |
+
|
| 574 |
// Get the attribute id for several attributes
|
| 575 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
| 576 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
| 577 |
$nameId = $eavAttribute->getIdByCode('catalog_product', 'name');
|
| 578 |
$priceId = $eavAttribute->getIdByCode('catalog_product', 'price');
|
| 579 |
+
|
| 580 |
// Loop through the stores
|
| 581 |
foreach (Mage::app()->getWebsites() as $website) {
|
| 582 |
// Get the website id
|
| 584 |
foreach ($website->getGroups() as $group) {
|
| 585 |
$stores = $group->getStores();
|
| 586 |
foreach ($stores as $store) {
|
| 587 |
+
|
| 588 |
// Get the store id
|
| 589 |
$storeId = $store->getStoreId();
|
| 590 |
// Init the store to be able to load the quote and the collections properly
|
| 591 |
Mage::app()->init($storeId,'store');
|
| 592 |
+
|
| 593 |
// Get the product collection
|
| 594 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
| 595 |
+
|
| 596 |
// If flat catalog is enabled
|
| 597 |
+
if (Mage::helper('catalog/product_flat')->isEnabled())
|
| 598 |
{
|
| 599 |
// First collection: carts with products that became on sale
|
| 600 |
// Join the collection with the required tables
|
| 682 |
null)
|
| 683 |
->order('quote_table.updated_at DESC');
|
| 684 |
}
|
| 685 |
+
|
| 686 |
//$collection->printlogquery(true,true);
|
| 687 |
$collection->load();
|
| 688 |
+
|
| 689 |
+
// Skip the rest of the code if the collection is empty
|
| 690 |
+
if ($collection->getSize() == 0) continue;
|
| 691 |
+
|
| 692 |
// Call iterator walk method with collection query string and callback method as parameters
|
| 693 |
// Has to be used to handle massive collection instead of foreach
|
| 694 |
Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array(array($this, 'generateRecipients')));
|
app/code/community/DigitalPianism/Abandonedcarts/etc/config.xml
CHANGED
|
@@ -4,7 +4,7 @@
|
|
| 4 |
|
| 5 |
<modules>
|
| 6 |
<DigitalPianism_Abandonedcarts>
|
| 7 |
-
<version>0.3.
|
| 8 |
</DigitalPianism_Abandonedcarts>
|
| 9 |
</modules>
|
| 10 |
|
| 4 |
|
| 5 |
<modules>
|
| 6 |
<DigitalPianism_Abandonedcarts>
|
| 7 |
+
<version>0.3.2</version>
|
| 8 |
</DigitalPianism_Abandonedcarts>
|
| 9 |
</modules>
|
| 10 |
|
app/code/community/DigitalPianism/Abandonedcarts/etc/system.xml
CHANGED
|
@@ -89,7 +89,7 @@
|
|
| 89 |
<show_in_store>1</show_in_store>
|
| 90 |
</enable_sale>
|
| 91 |
<email_template_sale translate="label">
|
| 92 |
-
<label>Email Template for
|
| 93 |
<frontend_type>select</frontend_type>
|
| 94 |
<source_model>adminhtml/system_config_source_email_template</source_model>
|
| 95 |
<sort_order>70</sort_order>
|
| 89 |
<show_in_store>1</show_in_store>
|
| 90 |
</enable_sale>
|
| 91 |
<email_template_sale translate="label">
|
| 92 |
+
<label>Email Template for Sale Products</label>
|
| 93 |
<frontend_type>select</frontend_type>
|
| 94 |
<source_model>adminhtml/system_config_source_email_template</source_model>
|
| 95 |
<sort_order>70</sort_order>
|
app/locale/en_US/DigitalPianism_Abandonedcarts.csv
CHANGED
|
@@ -13,4 +13,5 @@ Sender Email,Sender Email
|
|
| 13 |
Email Template for Unaltered Abandoned Carts,Email Template for Unaltered Abandoned Carts
|
| 14 |
Send Abandoned Cart Email After,Send Abandoned Cart Email After
|
| 15 |
(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.,(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.
|
| 16 |
-
Email Template for Sale Products,Email Template for Sale Products
|
|
|
| 13 |
Email Template for Unaltered Abandoned Carts,Email Template for Unaltered Abandoned Carts
|
| 14 |
Send Abandoned Cart Email After,Send Abandoned Cart Email After
|
| 15 |
(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.,(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.
|
| 16 |
+
Email Template for Sale Products,Email Template for Sale Products
|
| 17 |
+
Customer Groups Restriction,Customer Groups Restriction
|
app/locale/fr_FR/DigitalPianism_Abandonedcarts.csv
CHANGED
|
@@ -1,16 +1,17 @@
|
|
| 1 |
-
Abandoned Carts Email,Email des paniers abandonn
|
| 2 |
-
Abandoned Carts Emails,Emails des paniers abandonn
|
| 3 |
-
Enable Abandoned Carts Notification,Activer les notifications de paniers abandonn
|
| 4 |
-
Enable Sale Abandoned Carts Notification,Activer les notifications de paniers abandonn
|
| 5 |
Dry Run,Test
|
| 6 |
-
Setting this parameter to Yes will log all the email addresses supposed to receive a notification into the var/log/digitalpianism_abandonedcarts.log file and will not send the real email notification,Mettre la valeur
|
| 7 |
Test Email,Email de test
|
| 8 |
-
With dry run set to yes, this email is used to filter the emails supposed to be sent and only send a notification email to the customer with this email address,Avec Test
|
| 9 |
Send Notifications Now,Envoyer les notification maintenant
|
| 10 |
-
Cron Schedule,R
|
| 11 |
-
Sender Name,Nom de l'exp
|
| 12 |
-
Sender Email,Email de l'exp
|
| 13 |
-
Email Template for Unaltered Abandoned Carts,Gabarit d'email pour les paniers abandonn
|
| 14 |
-
Send Abandoned Cart Email After,Envoyer l'email de notification apr
|
| 15 |
-
(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.,(jours). NB: cela affecte seulement les paniers abandonn
|
| 16 |
-
Email Template for Sale Products,Gabarit d'email pour les produits en promo
|
|
|
| 1 |
+
Abandoned Carts Email,Email des paniers abandonnés
|
| 2 |
+
Abandoned Carts Emails,Emails des paniers abandonnés
|
| 3 |
+
Enable Abandoned Carts Notification,Activer les notifications de paniers abandonnés
|
| 4 |
+
Enable Sale Abandoned Carts Notification,Activer les notifications de paniers abandonnés en promo
|
| 5 |
Dry Run,Test
|
| 6 |
+
Setting this parameter to Yes will log all the email addresses supposed to receive a notification into the var/log/digitalpianism_abandonedcarts.log file and will not send the real email notification,Mettre la valeur à Oui enregistrera toutes les adresses emails supposées recevoir une notification dans le fichier var/log/digitalpianism_abandonedcarts.log et n'enverra pas les emails
|
| 7 |
Test Email,Email de test
|
| 8 |
+
With dry run set to yes, this email is used to filter the emails supposed to be sent and only send a notification email to the customer with this email address,Avec Test à Oui, cette adresse email sera utilisée pour filter les emails supposés être envoyé et seulement envoyé l'email de notification au client avec cette adresse
|
| 9 |
Send Notifications Now,Envoyer les notification maintenant
|
| 10 |
+
Cron Schedule,Réglage du cron
|
| 11 |
+
Sender Name,Nom de l'expéditeur
|
| 12 |
+
Sender Email,Email de l'expéditeur
|
| 13 |
+
Email Template for Unaltered Abandoned Carts,Gabarit d'email pour les paniers abandonnés non modifiés
|
| 14 |
+
Send Abandoned Cart Email After,Envoyer l'email de notification après
|
| 15 |
+
(days). NB: this only affects unaltered abandoned carts. If products go on sale, the email below is sent on the same day.,(jours). NB: cela affecte seulement les paniers abandonnés non modifiés. Si un des produits passent en promotion, l'email ci dessous sera envoyé le m�me jour.
|
| 16 |
+
Email Template for Sale Products,Gabarit d'email pour les produits en promo
|
| 17 |
+
Customer Groups Restriction,Restriction de groupes clients
|
package.xml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>DigitalPianism_Abandonedcarts</name>
|
| 4 |
-
<version>0.3.
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
| 7 |
<channel>community</channel>
|
|
@@ -95,11 +95,12 @@ Save the configuration.
|
|
| 95 |

|
| 96 |
<p>To manually trigger the notification system, please access System &gt; Configuration &gt; Digital Pianism &gt; Abandoned carts email and click on the "Send" button</p>
|
| 97 |
<p>Please note that this functionality will send abandoned carts notification regardless the delay you provided, all possible abandoned carts emails will be sent.</p></description>
|
| 98 |
-
<notes>- Fix
|
|
|
|
| 99 |
<authors><author><name>Digital Pianism</name><user>digitalpianism</user><email>contact@digital-pianism.com</email></author></authors>
|
| 100 |
-
<date>2015-11-
|
| 101 |
-
<time>15:
|
| 102 |
-
<contents><target name="magecommunity"><dir name="DigitalPianism"><dir name="Abandonedcarts"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Button.php" hash="1c8d9cad5c54bcc28c0760e72406b5e3"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="5148fe5929e61f4c8385c6c5be0b89f3"/></dir><dir name="Model"><file name="Observer.php" hash="
|
| 103 |
<compatible/>
|
| 104 |
<dependencies><required><php><min>4.1.0</min><max>6.0.0</max></php></required></dependencies>
|
| 105 |
</package>
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>DigitalPianism_Abandonedcarts</name>
|
| 4 |
+
<version>0.3.2</version>
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
| 7 |
<channel>community</channel>
|
| 95 |

|
| 96 |
<p>To manually trigger the notification system, please access System &gt; Configuration &gt; Digital Pianism &gt; Abandoned carts email and click on the "Send" button</p>
|
| 97 |
<p>Please note that this functionality will send abandoned carts notification regardless the delay you provided, all possible abandoned carts emails will be sent.</p></description>
|
| 98 |
+
<notes>- Fix encoding issue with french translations
|
| 99 |
+
- Add more translation</notes>
|
| 100 |
<authors><author><name>Digital Pianism</name><user>digitalpianism</user><email>contact@digital-pianism.com</email></author></authors>
|
| 101 |
+
<date>2015-11-24</date>
|
| 102 |
+
<time>15:15:20</time>
|
| 103 |
+
<contents><target name="magecommunity"><dir name="DigitalPianism"><dir name="Abandonedcarts"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Button.php" hash="1c8d9cad5c54bcc28c0760e72406b5e3"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="5148fe5929e61f4c8385c6c5be0b89f3"/></dir><dir name="Model"><file name="Observer.php" hash="86f9448aea6059484cb8aeb9e40af421"/><dir name="Sales"><dir name="Resource"><file name="Quote.php" hash="3b2f9f24a74a6ea3b6851d64bd6ae5ba"/></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="AbandonedcartsController.php" hash="c26ae0925cc1ca148f5e3277702842e2"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="8ddca513c0ed7e034c476f3e026ceda8"/><file name="config.xml" hash="81cd3beba01719cc31f571e29277e4e6"/><file name="system.xml" hash="07f261c1f35321317da8f09f75a37317"/></dir><dir name="sql"><dir name="abandonedcarts_setup"><file name="install-0.0.1.php" hash="851338e4a710b5d94fead688b065f4b5"/><file name="upgrade-0.0.1-0.0.2.php" hash="0227c009e49b97bcf3f34f84c49f0927"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="DigitalPianism_Abandonedcarts.xml" hash="8a7657855486c68d548db4ba48e083d2"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="digitalpianism"><dir name="abandonedcarts"><dir name="system"><dir name="config"><file name="button.phtml" hash="8f7e673ea52cd81b616cac01b1022990"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="magelocale"><dir name="en_US"><dir name="template"><dir name="email"><dir name="digitalpianism"><dir name="abandonedcarts"><file name="sales_abandonedcarts.html" hash="f8a5ec3af09730f06ade1fd18fa321e9"/><file name="sales_abandonedcarts_sale.html" hash="22bb7a1e95e336948a43f282e7e58806"/></dir></dir></dir></dir><file name="DigitalPianism_Abandonedcarts.csv" hash="b782bff95dba8b860cd773a674aac6c9"/></dir><dir name="fr_FR"><dir name="template"><dir name="email"><dir name="digitalpianism"><dir name="abandonedcarts"><file name="sales_abandonedcarts.html" hash="5340ea06fbf9d2213ea2f09e7425181b"/><file name="sales_abandonedcarts_sale.html" hash="22592c5467a554ab80195218bec5b6b0"/></dir></dir></dir></dir><file name="DigitalPianism_Abandonedcarts.csv" hash="0f5271e2ad1d6b07061314b18bd170c2"/></dir></target></contents>
|
| 104 |
<compatible/>
|
| 105 |
<dependencies><required><php><min>4.1.0</min><max>6.0.0</max></php></required></dependencies>
|
| 106 |
</package>
|
