DigitalPianism_Abandonedcarts - Version 0.1.13

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 CHANGED
@@ -21,7 +21,7 @@ class DigitalPianism_Abandonedcarts_Helper_Data extends Mage_Core_Helper_Abstrac
21
  */
22
  public function isEnabled()
23
  {
24
- return Mage::getStoreConfigFlag('abandonedcartsconfig/options/enable');
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::getStoreConfigFlag('abandonedcartsconfig/options/enable_sale');
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::getStoreConfigFlag('abandonedcartsconfig/options/dryrun');
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
- $quote->getResource()->saveAttribute($quote,array('abandoned_sale_notified'));
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
- $quote->getResource()->saveAttribute($quote,array('abandoned_notified'));
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
- // First collection: carts with products that became on sale
355
- // Join the collection with the required tables
356
- $collection->getSelect()
357
- ->reset(Zend_Db_Select::COLUMNS)
358
- ->columns(array('e.entity_id AS product_id',
359
- 'e.sku',
360
- /* Code if catalog flat is disabled
361
- 'catalog_name.value as product_name',
362
- 'catalog_price.value as product_price',
363
- 'catalog_special_price.value as product_special_price',
364
- 'catalog_special_from.value as product_special_from_date',
365
- 'catalog_special_to.value as product_special_to_date',
366
- */
367
- 'catalog_flat.name as product_name',
368
- 'catalog_flat.price as product_price',
369
- 'catalog_flat.special_price as product_special_price',
370
- 'catalog_flat.special_from_date as product_special_from_date',
371
- 'catalog_flat.special_to_date as product_special_to_date',
372
- 'quote_table.entity_id as cart_id',
373
- 'quote_table.updated_at as cart_updated_at',
374
- 'quote_table.abandoned_sale_notified as has_been_notified',
375
- 'quote_items.price as product_price_in_cart',
376
- 'quote_table.customer_email as customer_email',
377
- 'quote_table.customer_firstname as customer_firstname',
378
- 'quote_table.customer_lastname as customer_lastname'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  )
380
- )
381
- ->joinInner(
382
- array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
383
- 'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
384
- null)
385
- ->joinInner(
386
- array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
387
- '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,
388
- null)
389
- ->joinInner(
390
- array('catalog_flat' => Mage::getSingleton("core/resource")->getTableName('catalog_product_flat_'.$storeId)),
391
- 'catalog_flat.entity_id = e.entity_id',
392
- null)
393
- /* Code if catalog flat is disabled
394
- // Product Name
395
- ->joinInner(
396
- array('catalog_name' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_varchar')),
397
- 'catalog_name.entity_id = e.entity_id
398
- 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 = "name" AND eav_entity_type.entity_type_code = "catalog_product")
399
- AND catalog_name.store_id = '.$storeId,
400
- null)
401
- // Product Price
402
- ->joinInner(
403
- array('catalog_price' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
404
- 'catalog_price.entity_id = e.entity_id
405
- 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 = "price" AND eav_entity_type.entity_type_code = "catalog_product")
406
- AND catalog_price.store_id = '.$storeId,
407
- null)
408
- // Product Special Price
409
- ->joinInner(
410
- array('catalog_special_price' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
411
- 'catalog_special_price.entity_id = e.entity_id
412
- 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_price" AND eav_entity_type.entity_type_code = "catalog_product")
413
- AND catalog_special_price.store_id = '.$storeId,
414
- null)
415
- // Product Special Price From
416
- ->joinInner(
417
- array('catalog_special_from' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_datetime')),
418
- 'catalog_special_from.entity_id = e.entity_id
419
- 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_from" AND eav_entity_type.entity_type_code = "catalog_product")
420
- AND catalog_special_from.store_id = '.$storeId,
421
- null)
422
- // Product Special Price To
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
- //echo $collection->printlogquery(true);
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 the status attribute
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
- // First collection: carts with products that became on sale
516
- // Join the collection with the required tables
517
- $collection->getSelect()
518
- ->reset(Zend_Db_Select::COLUMNS)
519
- ->columns(array('e.entity_id AS product_id',
520
- 'e.sku',
521
- /* Code if catalog flat is disabled
522
- 'catalog_name.value as product_name',
523
- 'catalog_price.value as product_price',
524
- */
525
- 'catalog_flat.name as product_name',
526
- 'catalog_flat.price as product_price',
527
- 'quote_table.entity_id as cart_id',
528
- 'quote_table.updated_at as cart_updated_at',
529
- 'quote_table.abandoned_notified as has_been_notified',
530
- 'quote_table.customer_email as customer_email',
531
- 'quote_table.customer_firstname as customer_firstname',
532
- 'quote_table.customer_lastname as customer_lastname'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  )
534
- )
535
- ->joinInner(
536
- array('quote_items' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote_item')),
537
- 'quote_items.product_id = e.entity_id AND quote_items.price > 0.00',
538
- null)
539
- ->joinInner(
540
- array('quote_table' => Mage::getSingleton("core/resource")->getTableName('sales_flat_quote')),
541
- '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,
542
- null)
543
- ->joinInner(
544
- array('catalog_flat' => Mage::getSingleton("core/resource")->getTableName('catalog_product_flat_'.$storeId)),
545
- 'catalog_flat.entity_id = e.entity_id',
546
- null)
547
- /* Code if catalog flat is disabled
548
- // Product Name
549
- ->joinInner(
550
- array('catalog_name' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_varchar')),
551
- 'catalog_name.entity_id = e.entity_id
552
- 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 = "name" AND eav_entity_type.entity_type_code = "catalog_product")
553
- AND catalog_name.store_id = '.$storeId,
554
- null)
555
- // Product Price
556
- ->joinInner(
557
- array('catalog_price' => Mage::getSingleton("core/resource")->getTableName('catalog_product_entity_decimal')),
558
- 'catalog_price.entity_id = e.entity_id
559
- 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 = "price" AND eav_entity_type.entity_type_code = "catalog_product")
560
- AND catalog_price.store_id = '.$storeId,
561
- null)
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
- // echo $collection->printlogquery(true);
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.12</version>
8
  </DigitalPianism_Abandonedcarts>
9
  </modules>
10
 
@@ -65,24 +65,23 @@
65
  <abandonedcarts>
66
  <class>DigitalPianism_Abandonedcarts_Model</class>
67
  </abandonedcarts>
68
- <sales_resource>
69
- <rewrite>
70
- <!-- Mage_Sales_Model_Resource_Quote -->
71
- <quote>DigitalPianism_Abandonedcarts_Model_Sales_Resource_Quote</quote>
72
- </rewrite>
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/abandonedcarts/sales_abandonedcarts.html</file>
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/abandonedcarts/sales_abandonedcarts_sale.html</file>
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
- <cron_expr>0 0 * * *</cron_expr>
119
  </schedule>
120
  <run>
121
  <model>abandonedcarts/observer::sendAbandonedCartsEmail</model>
@@ -128,9 +127,7 @@
128
  <default>
129
  <abandonedcartsconfig>
130
  <options>
131
- <enable>0</enable>
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.12</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,8 +39,6 @@ Follow this link and log in to finalize your purchase with the new special price
39
  &#xD;
40
  &lt;h2&gt;Configuration&lt;/h2&gt;&#xD;
41
  &#xD;
42
- &lt;p&gt;For this module to work properly, you need to enable Flat Catalog Product under System &amp;gt; Configuration &amp;gt; Catalog &amp;gt; Catalog.&lt;/p&gt;&#xD;
43
- &#xD;
44
  &lt;h3&gt;Emails Design&lt;/h3&gt;&#xD;
45
  &#xD;
46
  &lt;ol&gt;&#xD;
@@ -57,6 +55,7 @@ Access the module configuration under System &amp;gt; Configuration &amp;gt; Dig
57
  &#xD;
58
  &lt;ul&gt;&#xD;
59
  &lt;li&gt;Enable Abandoned Carts Notification: setting this option to Yes will enabled the email notification for customers who abandoned their carts.&lt;/li&gt;&#xD;
 
60
  &lt;li&gt;Sender Name: here you can provide the sender name of the notification email&lt;/li&gt;&#xD;
61
  &lt;li&gt;Sender Email: here you can provide the sender email of the notification email&lt;/li&gt;&#xD;
62
  &lt;li&gt;Email Template for Unaltered Abandoned Carts: here you have to choose the email template you created previously for the "Abandoned Carts" email.&lt;/li&gt;&#xD;
@@ -74,8 +73,6 @@ Access the module configuration under System &amp;gt; Configuration &amp;gt; Dig
74
  &#xD;
75
  Save the configuration.&#xD;
76
  &#xD;
77
- &lt;p&gt;The emails are sent everyday at midnight via a cron job.&lt;/p&gt;&#xD;
78
- &#xD;
79
  &lt;h3&gt;Email Variables&lt;/h3&gt;&#xD;
80
  &#xD;
81
  &lt;p&gt;The following variables are being used in the email templates that come with the extension.&lt;/p&gt;&#xD;
@@ -98,11 +95,12 @@ Save the configuration.&#xD;
98
  &#xD;
99
  &lt;p&gt;To manually trigger the notification system, please access System &amp;gt; Configuration &amp;gt; Digital Pianism &amp;gt; Abandoned carts email and click on the "Send" button&lt;/p&gt;&#xD;
100
  &lt;p&gt;Please note that this functionality will send abandoned carts notification regardless the delay you provided, all possible abandoned carts emails will be sent.&lt;/p&gt;</description>
101
- <notes>- Bug Fixes</notes>
 
102
  <authors><author><name>Digital Pianism</name><user>digitalpianism</user><email>contact@digital-pianism.com</email></author></authors>
103
- <date>2015-07-06</date>
104
- <time>15:29:01</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="1a32f521774d20636c9861850fd32594"/></dir><dir name="Model"><file name="Observer.php" hash="90b9b844ccb8fd93873b034d7a1ed60a"/><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="48765d9eaca0c0dd56b9187c437ab347"/><file name="system.xml" hash="793efac0feb3c123a1c8869b21f302f1"/></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>
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
  &#xD;
40
  &lt;h2&gt;Configuration&lt;/h2&gt;&#xD;
41
  &#xD;
 
 
42
  &lt;h3&gt;Emails Design&lt;/h3&gt;&#xD;
43
  &#xD;
44
  &lt;ol&gt;&#xD;
55
  &#xD;
56
  &lt;ul&gt;&#xD;
57
  &lt;li&gt;Enable Abandoned Carts Notification: setting this option to Yes will enabled the email notification for customers who abandoned their carts.&lt;/li&gt;&#xD;
58
+ &lt;li&gt;Cron Schedule: here you can change the cron schedule time, it is set to 1AM by default.&lt;/li&gt;&#xD;
59
  &lt;li&gt;Sender Name: here you can provide the sender name of the notification email&lt;/li&gt;&#xD;
60
  &lt;li&gt;Sender Email: here you can provide the sender email of the notification email&lt;/li&gt;&#xD;
61
  &lt;li&gt;Email Template for Unaltered Abandoned Carts: here you have to choose the email template you created previously for the "Abandoned Carts" email.&lt;/li&gt;&#xD;
73
  &#xD;
74
  Save the configuration.&#xD;
75
  &#xD;
 
 
76
  &lt;h3&gt;Email Variables&lt;/h3&gt;&#xD;
77
  &#xD;
78
  &lt;p&gt;The following variables are being used in the email templates that come with the extension.&lt;/p&gt;&#xD;
95
  &#xD;
96
  &lt;p&gt;To manually trigger the notification system, please access System &amp;gt; Configuration &amp;gt; Digital Pianism &amp;gt; Abandoned carts email and click on the "Send" button&lt;/p&gt;&#xD;
97
  &lt;p&gt;Please note that this functionality will send abandoned carts notification regardless the delay you provided, all possible abandoned carts emails will be sent.&lt;/p&gt;</description>
98
+ <notes>- Configurable cron schedule&#xD;
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>