Version Notes
- Configurable cron schedule
- Support for websites with Flat Catalog disabled
Download this release
Release Info
Developer | Digital Pianism |
Extension | DigitalPianism_Abandonedcarts |
Version | 0.1.13 |
Comparing to | |
See all releases |
Code changes from version 0.1.12 to 0.1.13
- app/code/community/DigitalPianism/Abandonedcarts/Helper/Data.php +3 -3
- app/code/community/DigitalPianism/Abandonedcarts/Model/Observer.php +211 -145
- app/code/community/DigitalPianism/Abandonedcarts/etc/config.xml +10 -13
- app/code/community/DigitalPianism/Abandonedcarts/etc/system.xml +8 -0
- package.xml +7 -9
app/code/community/DigitalPianism/Abandonedcarts/Helper/Data.php
CHANGED
@@ -21,7 +21,7 @@ class DigitalPianism_Abandonedcarts_Helper_Data extends Mage_Core_Helper_Abstrac
|
|
21 |
*/
|
22 |
public function isEnabled()
|
23 |
{
|
24 |
-
return Mage::
|
25 |
}
|
26 |
|
27 |
/**
|
@@ -29,7 +29,7 @@ class DigitalPianism_Abandonedcarts_Helper_Data extends Mage_Core_Helper_Abstrac
|
|
29 |
*/
|
30 |
public function isSaleEnabled()
|
31 |
{
|
32 |
-
return Mage::
|
33 |
}
|
34 |
|
35 |
/**
|
@@ -37,7 +37,7 @@ class DigitalPianism_Abandonedcarts_Helper_Data extends Mage_Core_Helper_Abstrac
|
|
37 |
*/
|
38 |
public function getDryRun()
|
39 |
{
|
40 |
-
return Mage::
|
41 |
}
|
42 |
|
43 |
/**
|
21 |
*/
|
22 |
public function isEnabled()
|
23 |
{
|
24 |
+
return Mage::getStoreConfig('abandonedcartsconfig/options/enable');
|
25 |
}
|
26 |
|
27 |
/**
|
29 |
*/
|
30 |
public function isSaleEnabled()
|
31 |
{
|
32 |
+
return Mage::getStoreConfig('abandonedcartsconfig/options/enable_sale');
|
33 |
}
|
34 |
|
35 |
/**
|
37 |
*/
|
38 |
public function getDryRun()
|
39 |
{
|
40 |
+
return Mage::getStoreConfig('abandonedcartsconfig/options/dryrun');
|
41 |
}
|
42 |
|
43 |
/**
|
app/code/community/DigitalPianism/Abandonedcarts/Model/Observer.php
CHANGED
@@ -232,7 +232,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
232 |
// Save only if dryrun is false or if the test email is set and found
|
233 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
234 |
{
|
235 |
-
|
236 |
}
|
237 |
}
|
238 |
}
|
@@ -305,7 +305,7 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
305 |
// Save only if dryrun is false or if the test email is set and found
|
306 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
307 |
{
|
308 |
-
|
309 |
}
|
310 |
}
|
311 |
}
|
@@ -333,6 +333,11 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
333 |
// Get the attribute id for the status attribute
|
334 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
335 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
|
|
|
|
|
|
|
|
|
|
336 |
|
337 |
// Loop through the stores
|
338 |
foreach (Mage::app()->getWebsites() as $website) {
|
@@ -351,93 +356,122 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
351 |
// Get the product collection
|
352 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
353 |
|
354 |
-
//
|
355 |
-
|
356 |
-
$
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
)
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
->joinInner(
|
424 |
-
array('catalog_special_to' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_datetime')),
|
425 |
-
'catalog_special_to.entity_id = e.entity_id
|
426 |
-
AND attribute_id = (SELECT attribute_id FROM eav_attribute LEFT JOIN "eav_entity_type" ON eav_attribute.entity_type_id = eav_entity_type.entity_type_id WHERE eav_attribute.attribute_code = "special_to" AND eav_entity_type.entity_type_code = "catalog_product")
|
427 |
-
AND catalog_special_to.store_id = '.$storeId,
|
428 |
-
null)
|
429 |
-
*/
|
430 |
-
->joinInner(
|
431 |
-
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
432 |
-
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
433 |
-
null)
|
434 |
-
->joinInner(
|
435 |
-
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
436 |
-
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND inventory.website_id = '.$websiteId,
|
437 |
-
null)
|
438 |
-
->order('quote_table.updated_at DESC');
|
439 |
|
440 |
-
|
441 |
$collection->load();
|
442 |
|
443 |
// Skip the rest of the code if the collection is empty
|
@@ -492,9 +526,11 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
492 |
$delay = date('Y-m-d H:i:s', strtotime("+7 day"));
|
493 |
}
|
494 |
|
495 |
-
// Get the attribute id for
|
496 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
497 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
|
|
|
|
498 |
|
499 |
// Loop through the stores
|
500 |
foreach (Mage::app()->getWebsites() as $website) {
|
@@ -512,65 +548,95 @@ class DigitalPianism_Abandonedcarts_Model_Observer extends Mage_Core_Model_Abstr
|
|
512 |
// Get the product collection
|
513 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
514 |
|
515 |
-
//
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
533 |
)
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
*/
|
563 |
-
->joinInner(
|
564 |
-
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
565 |
-
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
566 |
-
null)
|
567 |
-
->joinInner(
|
568 |
-
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
569 |
-
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND website_id = '.$websiteId,
|
570 |
-
null)
|
571 |
-
->order('quote_table.updated_at DESC');
|
572 |
|
573 |
-
|
574 |
$collection->load();
|
575 |
|
576 |
// Call iterator walk method with collection query string and callback method as parameters
|
232 |
// Save only if dryrun is false or if the test email is set and found
|
233 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
234 |
{
|
235 |
+
$quote->getResource()->saveAttribute($quote,array('abandoned_sale_notified'));
|
236 |
}
|
237 |
}
|
238 |
}
|
305 |
// Save only if dryrun is false or if the test email is set and found
|
306 |
if (!$dryrun || (isset($testemail) && $email == $testemail))
|
307 |
{
|
308 |
+
$quote->getResource()->saveAttribute($quote,array('abandoned_notified'));
|
309 |
}
|
310 |
}
|
311 |
}
|
333 |
// Get the attribute id for the status attribute
|
334 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
335 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
336 |
+
$nameId = $eavAttribute->getIdByCode('catalog_product', 'name');
|
337 |
+
$priceId = $eavAttribute->getIdByCode('catalog_product', 'price');
|
338 |
+
$spriceId = $eavAttribute->getIdByCode('catalog_product', 'special_price');
|
339 |
+
$spfromId = $eavAttribute->getIdByCode('catalog_product', 'special_from_date');
|
340 |
+
$sptoId = $eavAttribute->getIdByCode('catalog_product', 'special_to_date');
|
341 |
|
342 |
// Loop through the stores
|
343 |
foreach (Mage::app()->getWebsites() as $website) {
|
356 |
// Get the product collection
|
357 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
358 |
|
359 |
+
// Database TableNams
|
360 |
+
$eavEntityType = Mage::getSingleton("core/resource")->getTableName('eav_entity_type');
|
361 |
+
$eavAttribute = Mage::getSingleton("core/resource")->getTableName('eav_attribute');
|
362 |
+
|
363 |
+
// If flat catalog is enabled
|
364 |
+
if (Mage::helper('catalog/product_flat')->isEnabled())
|
365 |
+
{
|
366 |
+
// First collection: carts with products that became on sale
|
367 |
+
// Join the collection with the required tables
|
368 |
+
$collection->getSelect()
|
369 |
+
->reset(Zend_Db_Select::COLUMNS)
|
370 |
+
->columns(array('e.entity_id AS product_id',
|
371 |
+
'e.sku',
|
372 |
+
'catalog_flat.name as product_name',
|
373 |
+
'catalog_flat.price as product_price',
|
374 |
+
'catalog_flat.special_price as product_special_price',
|
375 |
+
'catalog_flat.special_from_date as product_special_from_date',
|
376 |
+
'catalog_flat.special_to_date as product_special_to_date',
|
377 |
+
'quote_table.entity_id as cart_id',
|
378 |
+
'quote_table.updated_at as cart_updated_at',
|
379 |
+
'quote_table.abandoned_sale_notified as has_been_notified',
|
380 |
+
'quote_items.price as product_price_in_cart',
|
381 |
+
'quote_table.customer_email as customer_email',
|
382 |
+
'quote_table.customer_firstname as customer_firstname',
|
383 |
+
'quote_table.customer_lastname as customer_lastname'
|
384 |
+
)
|
385 |
+
)
|
386 |
+
->joinInner(
|
387 |
+
array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
|
388 |
+
'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
|
389 |
+
null)
|
390 |
+
->joinInner(
|
391 |
+
array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
|
392 |
+
'quote_items.quote_id = quote_table.entity_id AND quote_table.items_count > 0 AND quote_table.is_active = 1 AND quote_table.customer_email IS NOT NULL AND quote_table.abandoned_sale_notified = 0 AND quote_table.store_id = '.$storeId,
|
393 |
+
null)
|
394 |
+
->joinInner(
|
395 |
+
array('catalog_flat' => Mage::getSingleton("core/resource")->getTableName('catalog_product_flat_'.$storeId)),
|
396 |
+
'catalog_flat.entity_id = e.entity_id',
|
397 |
+
null)
|
398 |
+
->joinInner(
|
399 |
+
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
400 |
+
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
401 |
+
null)
|
402 |
+
->joinInner(
|
403 |
+
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
404 |
+
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND inventory.website_id = '.$websiteId,
|
405 |
+
null)
|
406 |
+
->order('quote_table.updated_at DESC');
|
407 |
+
}
|
408 |
+
else
|
409 |
+
{
|
410 |
+
// First collection: carts with products that became on sale
|
411 |
+
// Join the collection with the required tables
|
412 |
+
$collection->getSelect()
|
413 |
+
->reset(Zend_Db_Select::COLUMNS)
|
414 |
+
->columns(array('e.entity_id AS product_id',
|
415 |
+
'e.sku',
|
416 |
+
'catalog_name.value as product_name',
|
417 |
+
'catalog_price.value as product_price',
|
418 |
+
'catalog_sprice.value as product_special_price',
|
419 |
+
'catalog_spfrom.value as product_special_from_date',
|
420 |
+
'catalog_spto.value as product_special_to_date',
|
421 |
+
'quote_table.entity_id as cart_id',
|
422 |
+
'quote_table.updated_at as cart_updated_at',
|
423 |
+
'quote_table.abandoned_sale_notified as has_been_notified',
|
424 |
+
'quote_items.price as product_price_in_cart',
|
425 |
+
'quote_table.customer_email as customer_email',
|
426 |
+
'quote_table.customer_firstname as customer_firstname',
|
427 |
+
'quote_table.customer_lastname as customer_lastname'
|
428 |
+
)
|
429 |
)
|
430 |
+
// Name
|
431 |
+
->joinInner(
|
432 |
+
array('catalog_name' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_varchar')),
|
433 |
+
"catalog_name.entity_id = e.entity_id AND catalog_name.attribute_id = $nameId",
|
434 |
+
null)
|
435 |
+
// Price
|
436 |
+
->joinInner(
|
437 |
+
array('catalog_price' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
|
438 |
+
"catalog_price.entity_id = e.entity_id AND catalog_price.attribute_id = $priceId",
|
439 |
+
null)
|
440 |
+
// Special Price
|
441 |
+
->joinInner(
|
442 |
+
array('catalog_sprice' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
|
443 |
+
"catalog_sprice.entity_id = e.entity_id AND catalog_sprice.attribute_id = $spriceId",
|
444 |
+
null)
|
445 |
+
// Special From Date
|
446 |
+
->joinInner(
|
447 |
+
array('catalog_spfrom' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_datetime')),
|
448 |
+
"catalog_spfrom.entity_id = e.entity_id AND catalog_spfrom.attribute_id = $spfromId",
|
449 |
+
null)
|
450 |
+
// Special To Date
|
451 |
+
->joinInner(
|
452 |
+
array('catalog_spto' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_datetime')),
|
453 |
+
"catalog_spto.entity_id = e.entity_id AND catalog_spto.attribute_id = $sptoId",
|
454 |
+
null)
|
455 |
+
->joinInner(
|
456 |
+
array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
|
457 |
+
'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
|
458 |
+
null)
|
459 |
+
->joinInner(
|
460 |
+
array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
|
461 |
+
'quote_items.quote_id = quote_table.entity_id AND quote_table.items_count > 0 AND quote_table.is_active = 1 AND quote_table.customer_email IS NOT NULL AND quote_table.abandoned_sale_notified = 0 AND quote_table.store_id = '.$storeId,
|
462 |
+
null)
|
463 |
+
->joinInner(
|
464 |
+
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
465 |
+
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
466 |
+
null)
|
467 |
+
->joinInner(
|
468 |
+
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
469 |
+
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND inventory.website_id = '.$websiteId,
|
470 |
+
null)
|
471 |
+
->order('quote_table.updated_at DESC');
|
472 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
473 |
|
474 |
+
//$collection->printlogquery(true,true);
|
475 |
$collection->load();
|
476 |
|
477 |
// Skip the rest of the code if the collection is empty
|
526 |
$delay = date('Y-m-d H:i:s', strtotime("+7 day"));
|
527 |
}
|
528 |
|
529 |
+
// Get the attribute id for several attributes
|
530 |
$eavAttribute = Mage::getModel('eav/entity_attribute');
|
531 |
$statusId = $eavAttribute->getIdByCode('catalog_product', 'status');
|
532 |
+
$nameId = $eavAttribute->getIdByCode('catalog_product', 'name');
|
533 |
+
$priceId = $eavAttribute->getIdByCode('catalog_product', 'price');
|
534 |
|
535 |
// Loop through the stores
|
536 |
foreach (Mage::app()->getWebsites() as $website) {
|
548 |
// Get the product collection
|
549 |
$collection = Mage::getResourceModel('catalog/product_collection')->setStore($storeId);
|
550 |
|
551 |
+
// If flat catalog is enabled
|
552 |
+
if (Mage::helper('catalog/product_flat')->isEnabled())
|
553 |
+
{
|
554 |
+
// First collection: carts with products that became on sale
|
555 |
+
// Join the collection with the required tables
|
556 |
+
$collection->getSelect()
|
557 |
+
->reset(Zend_Db_Select::COLUMNS)
|
558 |
+
->columns(array('e.entity_id AS product_id',
|
559 |
+
'e.sku',
|
560 |
+
'catalog_flat.name as product_name',
|
561 |
+
'catalog_flat.price as product_price',
|
562 |
+
'quote_table.entity_id as cart_id',
|
563 |
+
'quote_table.updated_at as cart_updated_at',
|
564 |
+
'quote_table.abandoned_notified as has_been_notified',
|
565 |
+
'quote_table.customer_email as customer_email',
|
566 |
+
'quote_table.customer_firstname as customer_firstname',
|
567 |
+
'quote_table.customer_lastname as customer_lastname'
|
568 |
+
)
|
569 |
+
)
|
570 |
+
->joinInner(
|
571 |
+
array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
|
572 |
+
'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
|
573 |
+
null)
|
574 |
+
->joinInner(
|
575 |
+
array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
|
576 |
+
'quote_items.quote_id = quote_table.entity_id AND quote_table.items_count > 0 AND quote_table.is_active = 1 AND quote_table.customer_email IS NOT NULL AND quote_table.abandoned_notified = 0 AND quote_table.updated_at < "'.$delay.'" AND quote_table.store_id = '.$storeId,
|
577 |
+
null)
|
578 |
+
->joinInner(
|
579 |
+
array('catalog_flat' => Mage::getSingleton("core/resource")->getTableName('catalog_product_flat_'.$storeId)),
|
580 |
+
'catalog_flat.entity_id = e.entity_id',
|
581 |
+
null)
|
582 |
+
->joinInner(
|
583 |
+
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
584 |
+
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
585 |
+
null)
|
586 |
+
->joinInner(
|
587 |
+
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
588 |
+
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND website_id = '.$websiteId,
|
589 |
+
null)
|
590 |
+
->order('quote_table.updated_at DESC');
|
591 |
+
}
|
592 |
+
else
|
593 |
+
{
|
594 |
+
// First collection: carts with products that became on sale
|
595 |
+
// Join the collection with the required tables
|
596 |
+
$collection->getSelect()
|
597 |
+
->reset(Zend_Db_Select::COLUMNS)
|
598 |
+
->columns(array('e.entity_id AS product_id',
|
599 |
+
'e.sku',
|
600 |
+
'catalog_name.value as product_name',
|
601 |
+
'catalog_price.value as product_price',
|
602 |
+
'quote_table.entity_id as cart_id',
|
603 |
+
'quote_table.updated_at as cart_updated_at',
|
604 |
+
'quote_table.abandoned_notified as has_been_notified',
|
605 |
+
'quote_table.customer_email as customer_email',
|
606 |
+
'quote_table.customer_firstname as customer_firstname',
|
607 |
+
'quote_table.customer_lastname as customer_lastname'
|
608 |
+
)
|
609 |
)
|
610 |
+
// Name
|
611 |
+
->joinInner(
|
612 |
+
array('catalog_name' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_varchar')),
|
613 |
+
"catalog_name.entity_id = e.entity_id AND catalog_name.attribute_id = $nameId",
|
614 |
+
null)
|
615 |
+
// Price
|
616 |
+
->joinInner(
|
617 |
+
array('catalog_price' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
|
618 |
+
"catalog_price.entity_id = e.entity_id AND catalog_price.attribute_id = $priceId",
|
619 |
+
null)
|
620 |
+
->joinInner(
|
621 |
+
array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
|
622 |
+
'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
|
623 |
+
null)
|
624 |
+
->joinInner(
|
625 |
+
array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
|
626 |
+
'quote_items.quote_id = quote_table.entity_id AND quote_table.items_count > 0 AND quote_table.is_active = 1 AND quote_table.customer_email IS NOT NULL AND quote_table.abandoned_notified = 0 AND quote_table.updated_at < "'.$delay.'" AND quote_table.store_id = '.$storeId,
|
627 |
+
null)
|
628 |
+
->joinInner(
|
629 |
+
array('catalog_enabled' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_int')),
|
630 |
+
'catalog_enabled.entity_id = e.entity_id AND catalog_enabled.attribute_id = '.$statusId.' AND catalog_enabled.value = 1',
|
631 |
+
null)
|
632 |
+
->joinInner(
|
633 |
+
array('inventory' => Mage::getSingleton("core/resource")->getTableName('cataloginventory_stock_status')),
|
634 |
+
'inventory.product_id = e.entity_id AND inventory.stock_status = 1 AND website_id = '.$websiteId,
|
635 |
+
null)
|
636 |
+
->order('quote_table.updated_at DESC');
|
637 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
638 |
|
639 |
+
//$collection->printlogquery(true,true);
|
640 |
$collection->load();
|
641 |
|
642 |
// Call iterator walk method with collection query string and callback method as parameters
|
app/code/community/DigitalPianism/Abandonedcarts/etc/config.xml
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
<modules>
|
6 |
<DigitalPianism_Abandonedcarts>
|
7 |
-
<version>0.1.
|
8 |
</DigitalPianism_Abandonedcarts>
|
9 |
</modules>
|
10 |
|
@@ -65,24 +65,23 @@
|
|
65 |
<abandonedcarts>
|
66 |
<class>DigitalPianism_Abandonedcarts_Model</class>
|
67 |
</abandonedcarts>
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
</sales_resource>
|
74 |
</models>
|
75 |
|
76 |
<template>
|
77 |
<email>
|
78 |
<abandonedcartsconfig_options_email_template translate="label" module="abandonedcarts">
|
79 |
<label>Abandoned Cart Template</label>
|
80 |
-
<file>digitalpianism/
|
81 |
<type>html</type>
|
82 |
</abandonedcartsconfig_options_email_template>
|
83 |
<abandonedcartsconfig_options_email_template_sale translate="label" module="abandonedcarts">
|
84 |
<label>Abandoned Cart Sale Template</label>
|
85 |
-
<file>digitalpianism/
|
86 |
<type>html</type>
|
87 |
</abandonedcartsconfig_options_email_template_sale>
|
88 |
</email>
|
@@ -115,7 +114,7 @@
|
|
115 |
<jobs>
|
116 |
<digitalpianism_abandonedcarts_send>
|
117 |
<schedule>
|
118 |
-
<
|
119 |
</schedule>
|
120 |
<run>
|
121 |
<model>abandonedcarts/observer::sendAbandonedCartsEmail</model>
|
@@ -128,9 +127,7 @@
|
|
128 |
<default>
|
129 |
<abandonedcartsconfig>
|
130 |
<options>
|
131 |
-
<
|
132 |
-
<enable_sale>0</enable_sale>
|
133 |
-
<dryrun>0</dryrun>
|
134 |
<notify_delay>20</notify_delay>
|
135 |
<email_template>abandonedcartsconfig_options_email_template</email_template>
|
136 |
<email_template_sale>abandonedcartsconfig_options_email_template_sale</email_template_sale>
|
4 |
|
5 |
<modules>
|
6 |
<DigitalPianism_Abandonedcarts>
|
7 |
+
<version>0.1.13</version>
|
8 |
</DigitalPianism_Abandonedcarts>
|
9 |
</modules>
|
10 |
|
65 |
<abandonedcarts>
|
66 |
<class>DigitalPianism_Abandonedcarts_Model</class>
|
67 |
</abandonedcarts>
|
68 |
+
<sales_resource>
|
69 |
+
<rewrite>
|
70 |
+
<quote>DigitalPianism_Abandonedcarts_Model_Sales_Resource_Quote</quote>
|
71 |
+
</rewrite>
|
72 |
+
</sales_resource>
|
|
|
73 |
</models>
|
74 |
|
75 |
<template>
|
76 |
<email>
|
77 |
<abandonedcartsconfig_options_email_template translate="label" module="abandonedcarts">
|
78 |
<label>Abandoned Cart Template</label>
|
79 |
+
<file>digitalpianism/sales_abandonedcarts.html</file>
|
80 |
<type>html</type>
|
81 |
</abandonedcartsconfig_options_email_template>
|
82 |
<abandonedcartsconfig_options_email_template_sale translate="label" module="abandonedcarts">
|
83 |
<label>Abandoned Cart Sale Template</label>
|
84 |
+
<file>digitalpianism/sales_abandonedcarts_sale.html</file>
|
85 |
<type>html</type>
|
86 |
</abandonedcartsconfig_options_email_template_sale>
|
87 |
</email>
|
114 |
<jobs>
|
115 |
<digitalpianism_abandonedcarts_send>
|
116 |
<schedule>
|
117 |
+
<config_path>abandonedcartsconfig/options/cron_expr</config_path>
|
118 |
</schedule>
|
119 |
<run>
|
120 |
<model>abandonedcarts/observer::sendAbandonedCartsEmail</model>
|
127 |
<default>
|
128 |
<abandonedcartsconfig>
|
129 |
<options>
|
130 |
+
<cron_expr>0 1 * * *</cron_expr>
|
|
|
|
|
131 |
<notify_delay>20</notify_delay>
|
132 |
<email_template>abandonedcartsconfig_options_email_template</email_template>
|
133 |
<email_template_sale>abandonedcartsconfig_options_email_template_sale</email_template_sale>
|
app/code/community/DigitalPianism/Abandonedcarts/etc/system.xml
CHANGED
@@ -32,6 +32,14 @@
|
|
32 |
<show_in_website>1</show_in_website>
|
33 |
<show_in_store>1</show_in_store>
|
34 |
</enable>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
<name translate="label">
|
36 |
<label>Sender Name</label>
|
37 |
<frontend_type>text</frontend_type>
|
32 |
<show_in_website>1</show_in_website>
|
33 |
<show_in_store>1</show_in_store>
|
34 |
</enable>
|
35 |
+
<cron_expr translate="label">
|
36 |
+
<label>Cron Schedule</label>
|
37 |
+
<frontend_type>text</frontend_type>
|
38 |
+
<sort_order>15</sort_order>
|
39 |
+
<show_in_default>1</show_in_default>
|
40 |
+
<show_in_website>1</show_in_website>
|
41 |
+
<show_in_store>1</show_in_store>
|
42 |
+
</cron_expr>
|
43 |
<name translate="label">
|
44 |
<label>Sender Name</label>
|
45 |
<frontend_type>text</frontend_type>
|
package.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>DigitalPianism_Abandonedcarts</name>
|
4 |
-
<version>0.1.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
@@ -39,8 +39,6 @@ Follow this link and log in to finalize your purchase with the new special price
|
|
39 |

|
40 |
<h2>Configuration</h2>
|
41 |

|
42 |
-
<p>For this module to work properly, you need to enable Flat Catalog Product under System &gt; Configuration &gt; Catalog &gt; Catalog.</p>
|
43 |
-

|
44 |
<h3>Emails Design</h3>
|
45 |

|
46 |
<ol>
|
@@ -57,6 +55,7 @@ Access the module configuration under System &gt; Configuration &gt; Dig
|
|
57 |

|
58 |
<ul>
|
59 |
<li>Enable Abandoned Carts Notification: setting this option to Yes will enabled the email notification for customers who abandoned their carts.</li>
|
|
|
60 |
<li>Sender Name: here you can provide the sender name of the notification email</li>
|
61 |
<li>Sender Email: here you can provide the sender email of the notification email</li>
|
62 |
<li>Email Template for Unaltered Abandoned Carts: here you have to choose the email template you created previously for the "Abandoned Carts" email.</li>
|
@@ -74,8 +73,6 @@ Access the module configuration under System &gt; Configuration &gt; Dig
|
|
74 |

|
75 |
Save the configuration.
|
76 |

|
77 |
-
<p>The emails are sent everyday at midnight via a cron job.</p>
|
78 |
-

|
79 |
<h3>Email Variables</h3>
|
80 |

|
81 |
<p>The following variables are being used in the email templates that come with the extension.</p>
|
@@ -98,11 +95,12 @@ Save the configuration.
|
|
98 |

|
99 |
<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>
|
100 |
<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>
|
101 |
-
<notes>-
|
|
|
102 |
<authors><author><name>Digital Pianism</name><user>digitalpianism</user><email>contact@digital-pianism.com</email></author></authors>
|
103 |
-
<date>2015-07-
|
104 |
-
<time>
|
105 |
-
<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="d5a6f33d47d067fc09a7b7fe8eacd287"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="
|
106 |
<compatible/>
|
107 |
<dependencies><required><php><min>4.1.0</min><max>6.0.0</max></php></required></dependencies>
|
108 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>DigitalPianism_Abandonedcarts</name>
|
4 |
+
<version>0.1.13</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
39 |

|
40 |
<h2>Configuration</h2>
|
41 |

|
|
|
|
|
42 |
<h3>Emails Design</h3>
|
43 |

|
44 |
<ol>
|
55 |

|
56 |
<ul>
|
57 |
<li>Enable Abandoned Carts Notification: setting this option to Yes will enabled the email notification for customers who abandoned their carts.</li>
|
58 |
+
<li>Cron Schedule: here you can change the cron schedule time, it is set to 1AM by default.</li>
|
59 |
<li>Sender Name: here you can provide the sender name of the notification email</li>
|
60 |
<li>Sender Email: here you can provide the sender email of the notification email</li>
|
61 |
<li>Email Template for Unaltered Abandoned Carts: here you have to choose the email template you created previously for the "Abandoned Carts" email.</li>
|
73 |

|
74 |
Save the configuration.
|
75 |

|
|
|
|
|
76 |
<h3>Email Variables</h3>
|
77 |

|
78 |
<p>The following variables are being used in the email templates that come with the extension.</p>
|
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>- Configurable cron schedule
|
99 |
+
- Support for websites with Flat Catalog disabled</notes>
|
100 |
<authors><author><name>Digital Pianism</name><user>digitalpianism</user><email>contact@digital-pianism.com</email></author></authors>
|
101 |
+
<date>2015-07-22</date>
|
102 |
+
<time>11:41:57</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="d5a6f33d47d067fc09a7b7fe8eacd287"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="4eda7b865d023206a58a4178f7db81a5"/></dir><dir name="Model"><file name="Observer.php" hash="bbf901e5e623244b0a60cf3362c80628"/><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="ca68e31a5e41f036451a409a7eeaaa16"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="8ddca513c0ed7e034c476f3e026ceda8"/><file name="config.xml" hash="f62c5c11a0e1c99b1a03da4d0de4eec6"/><file name="system.xml" hash="d54fa8ad3607a7f54809f967ebff6ce6"/></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="30565f91c47913465fd184a214c14b23"/><file name="sales_abandonedcarts_sale.html" hash="3cdee557727cb0166741062e5fdcf06f"/></dir></dir></dir></dir><file name="DigitalPianism_Abandonedcarts.csv" hash="4e17b6cae58dd1cdcd43b1113e2e09f4"/></dir></target></contents>
|
104 |
<compatible/>
|
105 |
<dependencies><required><php><min>4.1.0</min><max>6.0.0</max></php></required></dependencies>
|
106 |
</package>
|