AnattaDesign_AbandonedCarts - Version 1.0.0

Version Notes

First version - Track abandoned carts & show a funnel report to show statistics

Download this release

Release Info

Developer Anatta Design
Extension AnattaDesign_AbandonedCarts
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (23) hide show
  1. app/code/local/AnattaDesign/AbandonedCarts/Block/Widget.php +5 -0
  2. app/code/local/AnattaDesign/AbandonedCarts/Helper/Data.php +127 -0
  3. app/code/local/AnattaDesign/AbandonedCarts/Model/Checkout/Onepage/Observer.php +112 -0
  4. app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Opstatistics.php +9 -0
  5. app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Opstatistics/Collection.php +9 -0
  6. app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Statistics.php +9 -0
  7. app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Statistics/Collection.php +9 -0
  8. app/code/local/AnattaDesign/AbandonedCarts/Model/Observer.php +68 -0
  9. app/code/local/AnattaDesign/AbandonedCarts/Model/Opstatistics.php +9 -0
  10. app/code/local/AnattaDesign/AbandonedCarts/Model/Statistics.php +75 -0
  11. app/code/local/AnattaDesign/AbandonedCarts/controllers/WidgetController.php +9 -0
  12. app/code/local/AnattaDesign/AbandonedCarts/etc/config.xml +177 -0
  13. app/code/local/AnattaDesign/AbandonedCarts/sql/anattadesign_abandonedcarts_setup/mysql4-install-1.0.php +39 -0
  14. app/design/adminhtml/default/default/layout/anattadesign_abandonedcarts.xml +16 -0
  15. app/design/adminhtml/default/default/template/anattadesign/abandonedcarts/widget.phtml +188 -0
  16. app/etc/modules/AnattaDesign_AbandonedCarts.xml +9 -0
  17. package.xml +18 -0
  18. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/ar-lt.jpg +0 -0
  19. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/ar-rt.jpg +0 -0
  20. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/logo.jpg +0 -0
  21. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/notifications-btm.gif +0 -0
  22. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/notifications.gif +0 -0
  23. skin/adminhtml/default/default/anattadesign/abandonedcarts/css/style.css +46 -0
app/code/local/AnattaDesign/AbandonedCarts/Block/Widget.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Block_Widget extends Mage_Core_Block_Template {
4
+
5
+ }
app/code/local/AnattaDesign/AbandonedCarts/Helper/Data.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Helper_Data extends Mage_Core_Helper_Abstract {
4
+
5
+ public function getStatisticsModel() {
6
+ if ( $this->isAwesomeCheckoutActive() ) {
7
+ return Mage::getModel( 'anattadesign_abandonedcarts/statistics' );
8
+ } else {
9
+ return Mage::getModel( 'anattadesign_abandonedcarts/opstatistics' );
10
+ }
11
+ }
12
+
13
+ public function isAwesomeCheckoutActive() {
14
+ return Mage::getConfig()->getModuleConfig( 'AnattaDesign_AwesomeCheckout' )->is( 'active', 'true' );
15
+ }
16
+
17
+ public function getMessage() {
18
+
19
+ $cache = Mage::getSingleton( 'core/cache' );
20
+ $payload = $cache->load( 'abandonedcart_payload' );
21
+
22
+ if ( $payload === false ) {
23
+
24
+ $payload = file_get_contents( 'http://api.anattadesign.com/abandonedcart/1alpha/fetch/payload' );
25
+ $contents = json_decode( $payload, true );
26
+
27
+ if ( $contents['status'] == 'success' ) {
28
+ $message = $this->isAwesomeCheckoutActive() ? $contents['data']['ac'] : $contents['data']['non-ac'];
29
+ // cache data for 2 days
30
+ $cache->save( $payload, 'abandonedcart_payload', array( 'abandonedcart' ), 2 * 24 * 60 * 60 );
31
+ } else {
32
+ $message = false;
33
+ }
34
+ } else {
35
+ $contents = json_decode( $payload, true );
36
+ $message = $this->isAwesomeCheckoutActive() ? $contents['data']['ac'] : $contents['data']['non-ac'];
37
+ }
38
+
39
+ return $message;
40
+ }
41
+
42
+ public function getCurrencySymbol() {
43
+ return Mage::app()->getLocale()->currency( Mage::app()->getStore()->getCurrentCurrencyCode() )->getSymbol();
44
+ }
45
+
46
+ public function getSalesVolume( $year, $month ) {
47
+
48
+ $cache = Mage::getSingleton( 'core/cache' );
49
+ $sales_volume = $cache->load( 'abandonedcart_sales_volume_' . $year . '_' . $month );
50
+
51
+ if ( $sales_volume === false ) {
52
+ // recalculate
53
+ $orderTotals = Mage::getModel( 'sales/order' )->getCollection()
54
+ ->addAttributeToFilter( 'status', Mage_Sales_Model_Order::STATE_COMPLETE )
55
+ ->addAttributeToFilter( 'created_at', array( 'from' => date( 'Y-m-01' ) ) )
56
+ ->addAttributeToSelect( 'grand_total' )
57
+ ->getColumnValues( 'grand_total' )
58
+ ;
59
+
60
+ $sales_volume = array_sum( $orderTotals );
61
+
62
+ // cache it
63
+ $cache->save( $sales_volume, 'abandonedcart_sales_volume_' . $year . '_' . $month, array( 'abandonedcart' ), 24 * 60 * 60 );
64
+ }
65
+
66
+ return $sales_volume;
67
+ }
68
+
69
+ public function trailingslashit( $string ) {
70
+ return $this->untrailingslashit( $string ) . '/';
71
+ }
72
+
73
+ public function untrailingslashit( $string ) {
74
+ return rtrim( $string, '/' );
75
+ }
76
+
77
+ public function ping() {
78
+
79
+ // Get current version of the extension
80
+ $connection = Mage::getSingleton( 'core/resource' )->getConnection( 'core_read' );
81
+ $stmt = $connection->query( "SELECT version FROM core_resource WHERE code='anattadesign_abandonedcarts_setup';" );
82
+ $data = $stmt->fetch();
83
+ $version = $data['version'];
84
+
85
+ $ping = array(
86
+ 'version' => $version,
87
+ 'site_name' => Mage::getStoreConfig( 'general/store_information/name' ),
88
+ 'url' => 'http://' . str_replace( array( 'http://', '/index.php/', '/index.php' ), '', Mage::getUrl() ) // making sure the url is in format - http://domain.com/
89
+ );
90
+
91
+ $ping['url'] = Mage::helper( 'anattadesign_abandonedcarts' )->trailingslashit( $ping['url'] );
92
+
93
+ // make call
94
+ $client = new Varien_Http_Client( 'http://api.anattadesign.com/abandonedcart/1alpha/collect/ping' );
95
+ $client->setMethod( Varien_Http_Client::POST );
96
+ $client->setParameterPost( 'ping', $ping );
97
+
98
+ try {
99
+ $response = $client->request();
100
+ if ( $response->isSuccessful() ) {
101
+ $json_response = json_decode( $response->getBody(), true );
102
+ $ping_success = $json_response['status'] == 'success' ? true : false;
103
+ }
104
+ } catch ( Exception $e ) {
105
+ $ping_success = false;
106
+ }
107
+
108
+ if ( $ping_success ) {
109
+ // make sure ping is not rescheduled anymore
110
+ Mage::getModel( 'core/config' )->deleteConfig( 'anattadesign_abandonedcarts_ping_rescheduled' );
111
+ } else {
112
+ // reschedule ping, increment counts if its already scheduled, so that we can see how many times it has failed
113
+ // $ping_rescheduled = Mage::getStoreConfig( 'anattadesign_abandonedcarts_ping_rescheduled' );
114
+ // Fetch directly from database to bypass Magento config cache.
115
+ // Its better to bypass cache and make a sql query in favor of performance, sql query is not gonna run up on frontend side, except when all the cache is refreshed & extension is upgraded
116
+ $stmt = $connection->query( "SELECT value FROM core_config_data WHERE path='anattadesign_abandonedcarts_ping_rescheduled' AND scope = 'default' AND scope_id = 0 LIMIT 1;" );
117
+ $data = $stmt->fetch();
118
+ if ( $data === false )
119
+ $ping_rescheduled = 1;
120
+ else
121
+ $ping_rescheduled = intval( $data['value'] ) + 1;
122
+
123
+ Mage::getModel( 'core/config' )->saveConfig( 'anattadesign_abandonedcarts_ping_rescheduled', $ping_rescheduled );
124
+ }
125
+ }
126
+
127
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Checkout/Onepage/Observer.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer {
4
+
5
+ protected $_model;
6
+
7
+ public function __construct() {
8
+ $this->_model = Mage::helper( 'anattadesign_abandonedcarts' )->getStatisticsModel();
9
+ }
10
+
11
+ public function getModel() {
12
+ return $this->_model;
13
+ }
14
+
15
+ public function getQuoteId() {
16
+ return Mage::getModel( 'checkout/cart' )->getQuote()->getId();
17
+ }
18
+
19
+ public function index( $observer ) {
20
+ $statistics = $this->getModel();
21
+
22
+ if ( !$this->getQuoteId() ) {
23
+ return;
24
+ }
25
+
26
+ if ( Mage::helper( 'anattadesign_abandonedcarts' )->isAwesomeCheckoutActive() ) {
27
+ $statistics->saveStepReached( 'shipping', $this->getQuoteId() );
28
+ } else {
29
+ if ( Mage::getSingleton( 'customer/session' )->isLoggedIn() ) {
30
+ $statistics->saveStepReached( 'billing', $this->getQuoteId() );
31
+ } else {
32
+ $statistics->saveStepReached( 'login', $this->getQuoteId() );
33
+ }
34
+ }
35
+ }
36
+
37
+ public function saveMethod( $observer ) {
38
+ $statistics = $this->getModel();
39
+ $statistics->saveStepMoved( 'login', $this->getQuoteId() );
40
+ $statistics->saveStepReached( 'billing', $this->getQuoteId() );
41
+ }
42
+
43
+ public function loginPost( $observer ) {
44
+ $location = Mage::getModel( 'customer/session' )->getBeforeAuthUrl();
45
+ if ( $location ) {
46
+ if ( strpos( $location, 'checkout/onepage' ) > 0 ) {
47
+ $statistics = $this->getModel();
48
+ $statistics->saveStepMoved( 'login', $this->getQuoteId() );
49
+ }
50
+ }
51
+ }
52
+
53
+ public function saveBilling( $observer ) {
54
+ $response = $observer->getEvent()->getData( 'controller_action' )->getResponse();
55
+ if ( $this->_isMovedToNextStep( $response ) ) {
56
+ $statistics = $this->getModel();
57
+ $statistics->saveStepMoved( 'billing', $this->getQuoteId() );
58
+ $statistics->saveStepReached( $this->_getNextStep( $response ), $this->getQuoteId() );
59
+ }
60
+ }
61
+
62
+ public function saveShipping( $observer ) {
63
+ $response = $observer->getEvent()->getData( 'controller_action' )->getResponse();
64
+ if ( $this->_isMovedToNextStep( $response ) ) {
65
+ $statistics = $this->getModel();
66
+ $statistics->saveStepMoved( 'shipping', $this->getQuoteId() );
67
+ $statistics->saveStepReached( $this->_getNextStep( $response ), $this->getQuoteId() );
68
+ }
69
+ }
70
+
71
+ public function saveShippingMethod( $observer ) {
72
+ $response = $observer->getEvent()->getData( 'controller_action' )->getResponse();
73
+ if ( $this->_isMovedToNextStep( $response ) ) {
74
+ $statistics = $this->getModel();
75
+ $statistics->saveStepMoved( 'shipping_method', $this->getQuoteId() );
76
+ $statistics->saveStepReached( $this->_getNextStep( $response ), $this->getQuoteId() );
77
+ }
78
+ }
79
+
80
+ public function savePayment( $observer ) {
81
+ $response = $observer->getEvent()->getData( 'controller_action' )->getResponse();
82
+ if ( $this->_isMovedToNextStep( $response ) ) {
83
+ $statistics = $this->getModel();
84
+ $statistics->saveStepMoved( 'payment', $this->getQuoteId() );
85
+ $statistics->saveStepReached( $this->_getNextStep( $response ), $this->getQuoteId() );
86
+ }
87
+ }
88
+
89
+ public function saveOrder( $observer ) {
90
+ $response = $observer->getEvent()->getData( 'controller_action' )->getResponse();
91
+ if ( $this->_isMovedToNextStep( $response ) ) {
92
+ $statistics = $this->getModel();
93
+ $statistics->saveStepMoved( 'review', $this->getQuoteId() );
94
+ }
95
+ }
96
+
97
+ protected function _getNextStep( Mage_Core_Controller_Response_Http $response ) {
98
+ $body = json_decode( $response->getBody() );
99
+ return $body->goto_section;
100
+ }
101
+
102
+ protected function _isMovedToNextStep( Mage_Core_Controller_Response_Http $response ) {
103
+ if ( $response->getHttpResponseCode() == 200 ) {
104
+ $body = json_decode( $response->getBody() );
105
+ if ( empty( $body->error ) ) {
106
+ return true;
107
+ }
108
+ }
109
+ return false;
110
+ }
111
+
112
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Opstatistics.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Mysql4_Opstatistics extends Mage_Core_Model_Mysql4_Abstract {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/opstatistics', 'statistics_id' );
7
+ }
8
+
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Opstatistics/Collection.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Mysql4_Opstatistics_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/opstatistics' );
7
+ }
8
+
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Statistics.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Mysql4_Statistics extends Mage_Core_Model_Mysql4_Abstract {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/statistics', 'statistics_id' );
7
+ }
8
+
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Mysql4/Statistics/Collection.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Mysql4_Statistics_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/statistics' );
7
+ }
8
+
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Observer.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Observer {
4
+
5
+ public function uponAdminLogin() {
6
+ $this->ping();
7
+ $this->checkLatestVersion();
8
+ }
9
+
10
+ public function ping() {
11
+ // Instead of using getStoreConfig make a direct sql query to bypass magento cache
12
+ // $is_ping_rescheduled = Mage::getStoreConfig( 'anattadesign_abandonedcarts_ping_rescheduled' );
13
+ $connection = Mage::getSingleton( 'core/resource' )->getConnection( 'core_read' );
14
+ $stmt = $connection->query( "SELECT value FROM core_config_data WHERE path='anattadesign_abandonedcarts_ping_rescheduled' AND scope = 'default' AND scope_id = 0 LIMIT 1;" );
15
+ $data = $stmt->fetch();
16
+ // If $data is false, then that means there is no row in the table, and no ping has been rescheduled
17
+ if ( $data !== false )
18
+ Mage::helper( 'anattadesign_abandonedcarts' )->ping();
19
+ }
20
+
21
+ public function checkLatestVersion() {
22
+ $contents = file_get_contents( 'http://api.anattadesign.com/abandonedcart/1alpha/status/latestVersion' );
23
+ $latest = json_decode( $contents );
24
+
25
+ if ( $latest->status == "success" ) {
26
+
27
+ if ( $latest->latestVersion == Mage::getStoreConfig( 'anattadesign_abandonedcart_latest_checked_version' ) )
28
+ return;
29
+
30
+ $connection = Mage::getSingleton( 'core/resource' )->getConnection( 'core_read' );
31
+ $stmt = $connection->query( "SELECT version FROM core_resource WHERE code='anattadesign_abandonedcarts_setup'" );
32
+ $data = $stmt->fetch();
33
+ $version = $data['version'];
34
+
35
+ if ( $latest->latestVersion != $version ) {
36
+ Mage::getModel( 'adminnotification/inbox' )
37
+ ->setSeverity( Mage_AdminNotification_Model_Inbox::SEVERITY_NOTICE )
38
+ ->setTitle( "My Abandoned Cart {$latest->latestVersion} is now available" )
39
+ ->setDateAdded( gmdate( 'Y-m-d H:i:s' ) )
40
+ ->setUrl( 'http://www.myabandonedcarts.com/' )
41
+ ->setDescription( 'Your version of My Abandoned Cart is currently not up-to-date. Please <a href="http://www.myabandonedcarts.com/">click here</a> to get the latest version.' )
42
+ ->save();
43
+ Mage::getModel( 'core/config' )->saveConfig( 'anattadesign_abandonedcart_latest_checked_version', $latest->latestVersion );
44
+ }
45
+ }
46
+ }
47
+
48
+ public function addJavascriptBlock( $observer ) {
49
+
50
+ $controller = $observer->getAction();
51
+
52
+ if ( !$controller instanceof Mage_Adminhtml_DashboardController )
53
+ return;
54
+
55
+ $layout = $controller->getLayout();
56
+ $block = $layout->createBlock( 'core/text' );
57
+ $block->setText(
58
+ '<script type="text/javascript">
59
+ var anattadesign_abandonedcarts = {
60
+ url: "' . Mage::helper( 'adminhtml' )->getUrl( 'abandonedcarts/widget/render/' ) . '"
61
+ };
62
+ </script>'
63
+ );
64
+
65
+ $layout->getBlock( 'js' )->append( $block );
66
+ }
67
+
68
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Opstatistics.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Opstatistics extends AnattaDesign_AbandonedCarts_Model_Statistics {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/opstatistics' );
7
+ }
8
+
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/Model/Statistics.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_Model_Statistics extends Mage_Core_Model_Abstract {
4
+
5
+ protected function _construct() {
6
+ $this->_init( 'anattadesign_abandonedcarts/statistics' );
7
+ }
8
+
9
+ /**
10
+ * Save moved to step for quote.
11
+ *
12
+ * @param string $step
13
+ * @param int $quoteId
14
+ * @return AnattaDesign_AbandonedCarts_Model_Statistics
15
+ */
16
+ public function saveStepMoved( $step, $quoteId ) {
17
+ return $this->_saveStepData( array( 'step' => $step, 'quoteId' => $quoteId, 'moved' => 1 ) );
18
+ }
19
+
20
+ /**
21
+ * Save reached step for quote.
22
+ *
23
+ * @param string $step
24
+ * @param int $quoteId
25
+ * @return AnattaDesign_AbandonedCarts_Model_Statistics
26
+ */
27
+ public function saveStepReached( $step, $quoteId ) {
28
+ $data = array(
29
+ 'step' => $step,
30
+ 'quoteId' => $quoteId,
31
+ 'reached' => 1,
32
+ 'year' => date( 'Y' ),
33
+ 'month' => date( 'n' ),
34
+ 'date' => date( 'Y-m-d h:i:s' )
35
+ );
36
+ return $this->_saveStepData( $data );
37
+ }
38
+
39
+ /**
40
+ * Save step data.
41
+ * Step and quote id are required.
42
+ *
43
+ * @param array $data
44
+ * @throws Exception
45
+ * @return AnattaDesign_AbandonedCarts_Model_Statistics
46
+ */
47
+ protected function _saveStepData( array $data ) {
48
+ if ( !array_key_exists( 'step', $data ) ) {
49
+ throw new Exception( 'Step key is required' );
50
+ }
51
+
52
+ // Prepare data
53
+ $data = array_merge( $data, array(
54
+ 'sales_flat_quote_id' => $data['quoteId']
55
+ )
56
+ );
57
+
58
+ // Get existing statistics for this quote and step
59
+ $collection = $this->getCollection();
60
+ $collection->addFieldToFilter( 'sales_flat_quote_id', $data['quoteId'] );
61
+ $collection->addFieldToFilter( 'step', $data['step'] );
62
+
63
+ // TODO: Add date field to filter < 1 month
64
+
65
+ $collection->addOrder( 'statistics_id' );
66
+ $collection->load();
67
+
68
+ if ( count( $collection ) ) {
69
+ return $collection->fetchItem()->addData( $data )->save();
70
+ } else {
71
+ return $this->addData( $data )->save();
72
+ }
73
+ }
74
+
75
+ }
app/code/local/AnattaDesign/AbandonedCarts/controllers/WidgetController.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class AnattaDesign_AbandonedCarts_WidgetController extends Mage_Adminhtml_Controller_Action {
4
+
5
+ public function renderAction() {
6
+ $html = $this->getLayout()->createBlock( 'anattadesign_abandonedcarts/widget', 'root' )->setTemplate( 'anattadesign/abandonedcarts/widget.phtml' )->toHtml();
7
+ $this->getResponse()->setBody( $html );
8
+ }
9
+ }
app/code/local/AnattaDesign/AbandonedCarts/etc/config.xml ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <config>
3
+ <modules>
4
+ <AnattaDesign_AbandonedCarts>
5
+ <version>1.0.0</version>
6
+ </AnattaDesign_AbandonedCarts>
7
+ </modules>
8
+ <global>
9
+ <models>
10
+ <anattadesign_abandonedcarts>
11
+ <class>AnattaDesign_AbandonedCarts_Model</class>
12
+ <resourceModel>anattadesign_abandonedcarts_mysql4</resourceModel>
13
+ </anattadesign_abandonedcarts>
14
+ <anattadesign_abandonedcarts_mysql4>
15
+ <class>AnattaDesign_AbandonedCarts_Model_Mysql4</class>
16
+ <entities>
17
+ <statistics>
18
+ <table>anattadesign_abandonedcarts_statistics</table>
19
+ </statistics>
20
+ <opstatistics>
21
+ <table>anattadesign_abandonedcarts_opstatistics</table>
22
+ </opstatistics>
23
+ </entities>
24
+ </anattadesign_abandonedcarts_mysql4>
25
+ </models>
26
+ <blocks>
27
+ <anattadesign_abandonedcarts>
28
+ <class>AnattaDesign_AbandonedCarts_Block</class>
29
+ </anattadesign_abandonedcarts>
30
+ </blocks>
31
+ <resources>
32
+ <anattadesign_abandonedcarts_setup>
33
+ <setup>
34
+ <module>AnattaDesign_AbandonedCarts</module>
35
+ <class>Mage_Eav_Model_Entity_Setup</class>
36
+ </setup>
37
+ <connection>
38
+ <use>core_setup</use>
39
+ </connection>
40
+ </anattadesign_abandonedcarts_setup>
41
+ </resources>
42
+ <helpers>
43
+ <anattadesign_abandonedcarts>
44
+ <class>AnattaDesign_AbandonedCarts_Helper</class>
45
+ </anattadesign_abandonedcarts>
46
+ </helpers>
47
+ <translate>
48
+ <modules>
49
+ <AnattaDesign_AbandonedCarts>
50
+ <files>
51
+ <default>AnattaDesign_AbandonedCarts.csv</default>
52
+ </files>
53
+ </AnattaDesign_AbandonedCarts>
54
+ </modules>
55
+ </translate>
56
+ <events>
57
+ <admin_session_user_login_success>
58
+ <observers>
59
+ <anattadesign_abandonedcarts_model_observer>
60
+ <class>AnattaDesign_AbandonedCarts_Model_Observer</class>
61
+ <method>uponAdminLogin</method>
62
+ </anattadesign_abandonedcarts_model_observer>
63
+ </observers>
64
+ </admin_session_user_login_success>
65
+ <controller_action_layout_generate_blocks_after>
66
+ <observers>
67
+ <anattadesign_awesomecheckout_addjs>
68
+ <!--<type>singleton</type>-->
69
+ <class>AnattaDesign_AbandonedCarts_Model_Observer</class>
70
+ <method>addJavascriptBlock</method>
71
+ </anattadesign_awesomecheckout_addjs>
72
+ </observers>
73
+ </controller_action_layout_generate_blocks_after>
74
+ <controller_action_postdispatch_checkout_onepage_index>
75
+ <observers>
76
+ <anattadesign_abandonedcarts_checkout_observer>
77
+ <type>singleton</type>
78
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
79
+ <method>index</method>
80
+ </anattadesign_abandonedcarts_checkout_observer>
81
+ </observers>
82
+ </controller_action_postdispatch_checkout_onepage_index>
83
+ <controller_action_postdispatch_checkout_onepage_saveMethod>
84
+ <observers>
85
+ <anattadesign_abandonedcarts_checkout_observer>
86
+ <type>singleton</type>
87
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
88
+ <method>saveMethod</method>
89
+ </anattadesign_abandonedcarts_checkout_observer>
90
+ </observers>
91
+ </controller_action_postdispatch_checkout_onepage_saveMethod>
92
+ <controller_action_predispatch_customer_account_loginPost>
93
+ <observers>
94
+ <anattadesign_abandonedcarts_checkout_observer>
95
+ <type>singleton</type>
96
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
97
+ <method>loginPost</method>
98
+ </anattadesign_abandonedcarts_checkout_observer>
99
+ </observers>
100
+ </controller_action_predispatch_customer_account_loginPost>
101
+ <controller_action_postdispatch_checkout_onepage_saveBilling>
102
+ <observers>
103
+ <anattadesign_abandonedcarts_checkout_observer>
104
+ <type>singleton</type>
105
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
106
+ <method>saveBilling</method>
107
+ </anattadesign_abandonedcarts_checkout_observer>
108
+ </observers>
109
+ </controller_action_postdispatch_checkout_onepage_saveBilling>
110
+ <controller_action_postdispatch_checkout_onepage_saveShipping>
111
+ <observers>
112
+ <anattadesign_abandonedcarts_checkout_observer>
113
+ <type>singleton</type>
114
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
115
+ <method>saveShipping</method>
116
+ </anattadesign_abandonedcarts_checkout_observer>
117
+ </observers>
118
+ </controller_action_postdispatch_checkout_onepage_saveShipping>
119
+ <controller_action_postdispatch_checkout_onepage_saveShippingMethod>
120
+ <observers>
121
+ <anattadesign_abandonedcarts_checkout_observer>
122
+ <type>singleton</type>
123
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
124
+ <method>saveShippingMethod</method>
125
+ </anattadesign_abandonedcarts_checkout_observer>
126
+ </observers>
127
+ </controller_action_postdispatch_checkout_onepage_saveShippingMethod>
128
+ <controller_action_postdispatch_checkout_onepage_savePayment>
129
+ <observers>
130
+ <anattadesign_abandonedcarts_checkout_observer>
131
+ <type>singleton</type>
132
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
133
+ <method>savePayment</method>
134
+ </anattadesign_abandonedcarts_checkout_observer>
135
+ </observers>
136
+ </controller_action_postdispatch_checkout_onepage_savePayment>
137
+ <controller_action_postdispatch_checkout_onepage_saveOrder>
138
+ <observers>
139
+ <anattadesign_abandonedcarts_checkout_observer>
140
+ <type>singleton</type>
141
+ <class>AnattaDesign_AbandonedCarts_Model_Checkout_Onepage_Observer</class>
142
+ <method>saveOrder</method>
143
+ </anattadesign_abandonedcarts_checkout_observer>
144
+ </observers>
145
+ </controller_action_postdispatch_checkout_onepage_saveOrder>
146
+ </events>
147
+ </global>
148
+ <admin>
149
+ <routers>
150
+ <abandonedcarts>
151
+ <use>admin</use>
152
+ <args>
153
+ <module>AnattaDesign_AbandonedCarts</module>
154
+ <frontName>abandonedcarts</frontName>
155
+ </args>
156
+ </abandonedcarts>
157
+ </routers>
158
+ </admin>
159
+ <adminhtml>
160
+ <translate>
161
+ <modules>
162
+ <AnattaDesign_AbandonedCarts>
163
+ <files>
164
+ <default>AnattaDesign_AbandonedCarts.csv</default>
165
+ </files>
166
+ </AnattaDesign_AbandonedCarts>
167
+ </modules>
168
+ </translate>
169
+ <layout>
170
+ <updates>
171
+ <anattadesign_abandonedcarts>
172
+ <file>anattadesign_abandonedcarts.xml</file>
173
+ </anattadesign_abandonedcarts>
174
+ </updates>
175
+ </layout>
176
+ </adminhtml>
177
+ </config>
app/code/local/AnattaDesign/AbandonedCarts/sql/anattadesign_abandonedcarts_setup/mysql4-install-1.0.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+
5
+ $installer->startSetup();
6
+
7
+ $installer->run(
8
+ "CREATE TABLE `" . $installer->getTable( 'anattadesign_abandonedcarts/opstatistics' ) . "` (
9
+ `statistics_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
10
+ `sales_flat_quote_id` int(10) unsigned NOT NULL,
11
+ `step` varchar(32) NOT NULL,
12
+ `reached` tinyint(4) NOT NULL DEFAULT '0',
13
+ `moved` tinyint(4) NOT NULL DEFAULT '0',
14
+ `year` smallint(6) NOT NULL,
15
+ `month` tinyint(4) NOT NULL,
16
+ `date` datetime NOT NULL,
17
+ PRIMARY KEY (`statistics_id`),
18
+ KEY `dashboard_tab` (`year`,`month`,`step`,`reached`,`moved`)
19
+ ) ENGINE=InnoDB"
20
+ );
21
+
22
+ $installer->run(
23
+ "CREATE TABLE `" . $installer->getTable( 'anattadesign_abandonedcarts/statistics' ) . "` (
24
+ `statistics_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
25
+ `sales_flat_quote_id` int(10) unsigned NOT NULL,
26
+ `step` varchar(32) NOT NULL,
27
+ `reached` tinyint(4) NOT NULL DEFAULT '0',
28
+ `moved` tinyint(4) NOT NULL DEFAULT '0',
29
+ `year` smallint(6) NOT NULL,
30
+ `month` tinyint(4) NOT NULL,
31
+ `date` datetime NOT NULL,
32
+ PRIMARY KEY (`statistics_id`),
33
+ KEY `dashboard_tab` (`year`,`month`,`step`,`reached`,`moved`)
34
+ ) ENGINE=InnoDB"
35
+ );
36
+
37
+ $installer->endSetup();
38
+
39
+ Mage::helper( 'anattadesign_abandonedcarts' )->ping();
app/design/adminhtml/default/default/layout/anattadesign_abandonedcarts.xml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <layout>
3
+ <adminhtml_dashboard_index>
4
+ <reference name="head">
5
+ <action method="addCss">
6
+ <stylesheet>anattadesign/abandonedcarts/css/style.css</stylesheet>
7
+ </action>
8
+ <action method="addJs">
9
+ <script>anattadesign/abandonedcarts/zepto.js</script>
10
+ </action>
11
+ <action method="addJs">
12
+ <script>anattadesign/abandonedcarts/adminhack.js</script>
13
+ </action>
14
+ </reference>
15
+ </adminhtml_dashboard_index>
16
+ </layout>
app/design/adminhtml/default/default/template/anattadesign/abandonedcarts/widget.phtml ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !Mage::helper( 'core' )->isModuleEnabled( 'AnattaDesign_AbandonedCarts' ) ) {
3
+ die();
4
+ }
5
+ ?>
6
+
7
+ <link href='http://fonts.googleapis.com/css?family=Exo:600' rel='stylesheet' type='text/css'>
8
+ <link href='http://fonts.googleapis.com/css?family=Exo:100' rel='stylesheet' type='text/css'>
9
+ <link href='http://fonts.googleapis.com/css?family=Arvo' rel='stylesheet' type='text/css'>
10
+ <link href='http://fonts.googleapis.com/css?family=Ubuntu:400,500' rel='stylesheet' type='text/css'>
11
+
12
+ <?php
13
+ $display_month = array(
14
+ 1 => 'January',
15
+ 2 => 'February',
16
+ 3 => 'March',
17
+ 4 => 'April',
18
+ 5 => 'May',
19
+ 6 => 'June',
20
+ 7 => 'July',
21
+ 8 => 'August',
22
+ 9 => 'September',
23
+ 10 => 'October',
24
+ 11 => 'November',
25
+ 12 => 'December'
26
+ );
27
+
28
+ $current_year = date( 'Y' );
29
+
30
+ if ( isset( $_GET['month'] ) && intval( abs( $_GET['month'] ) ) != 0 ) {
31
+ $queried_month = intval( abs( $_GET['month'] ) );
32
+ } else {
33
+ $queried_month = date( 'm' );
34
+ }
35
+
36
+ if ( isset( $_GET['year'] ) && intval( abs( $_GET['year'] ) ) != 0 ) {
37
+ $queried_year = intval( abs( $_GET['year'] ) );
38
+ } else {
39
+ $queried_year = $current_year;
40
+ }
41
+
42
+ // Select table name where data is stored
43
+ if ( Mage::helper( 'anattadesign_abandonedcarts' )->isAwesomeCheckoutActive() ) {
44
+
45
+ $steps = array(
46
+ 0 => array(
47
+ 'step' => 'shipping'
48
+ ),
49
+ 1 => array(
50
+ 'step' => 'shipping_method'
51
+ ),
52
+ 2 => array(
53
+ 'step' => 'payment'
54
+ ),
55
+ 3 => array(
56
+ 'step' => 'review'
57
+ )
58
+ );
59
+ $table = 'anattadesign_abandonedcarts_statistics';
60
+ } else {
61
+
62
+ $steps = array(
63
+ 0 => array(
64
+ 'step' => 'login'
65
+ ),
66
+ 1 => array(
67
+ 'step' => 'billing'
68
+ ),
69
+ 2 => array(
70
+ 'step' => 'shipping'
71
+ ),
72
+ 3 => array(
73
+ 'step' => 'shipping_method'
74
+ ),
75
+ 4 => array(
76
+ 'step' => 'payment'
77
+ ),
78
+ 5 => array(
79
+ 'step' => 'review'
80
+ )
81
+ );
82
+
83
+ $table = 'anattadesign_abandonedcarts_opstatistics';
84
+ }
85
+
86
+ // Add reached & moved values in array
87
+ $connection = Mage::getSingleton( 'core/resource' )->getConnection( 'core_read' );
88
+ foreach ( $steps as &$step ) {
89
+ $query = "SELECT sum(reached) as reached, sum(moved) as moved FROM $table WHERE month = $queried_month AND year = $queried_year AND step = '" . $step['step'] . "';";
90
+ $resource = $connection->query( $query );
91
+ $fetched_data = $resource->fetch();
92
+ $step['reached'] = intval( $fetched_data['reached'] );
93
+ $step['moved'] = intval( $fetched_data['moved'] );
94
+ $step['loss'] = $step['reached'] == $step['moved'] ? 0 : ( $step['reached'] - $step['moved'] ) * 100 / $step['reached'];
95
+ unset( $step );
96
+ }
97
+
98
+ $step_no = 1;
99
+ $step_names = array(
100
+ 'login' => 'Login',
101
+ 'billing' => 'Billing',
102
+ 'shipping' => 'Shipping',
103
+ 'shipping_method' => 'Shipping Method',
104
+ 'payment' => 'Payment',
105
+ 'review' => 'Review'
106
+ );
107
+
108
+ // adjustments to data
109
+ if ( Mage::helper( 'anattadesign_abandonedcarts' )->isAwesomeCheckoutActive() ) {
110
+
111
+ } else {
112
+ // make sure login[reached] is not smaller than billing[reached] (for the sake of funnel)
113
+ $steps[0]['reached'] = max( $steps[0]['reached'], $steps[1]['reached'] );
114
+ // make sure shipping step which is optional only depicts the loss, so add padding here (for the sake of funnel)
115
+ $diff = $steps[1]['moved'] - $steps[2]['reached'];
116
+ $steps[2]['reached']+= $diff;
117
+ $steps[2]['moved']+= $diff;
118
+ }
119
+
120
+ // calculate abandonment rate & loss for the queried month-year
121
+ $abandonedment_rate = $steps[0]['reached'] == $steps[count( $steps ) - 1]['moved'] ? 0 : round( ( $steps[0]['reached'] - $steps[count( $steps ) - 1]['moved'] ) * 100 / $steps[0]['reached'], 2 );
122
+ $approx_loss = ( Mage::helper( 'anattadesign_abandonedcarts' )->getSalesVolume( $queried_year, $queried_month ) * ( $abandonedment_rate / 100 ) ) / ( 1 - ( $abandonedment_rate / 100 ) );
123
+ $approx_loss = Mage::helper( 'core' )->currency( $approx_loss, true, false );
124
+
125
+ // Get message to display user
126
+ $message = Mage::helper( 'anattadesign_abandonedcarts' )->getMessage();
127
+ ?>
128
+
129
+ <div id="ac-wrapper">
130
+ <!--header-->
131
+ <header id="ac-header">
132
+ <img class="left" src="<?php echo $this->getSkinUrl( 'anattadesign/abandonedcarts/css/images/logo.jpg' ); ?>" alt="Abandoned Cart"><!--logo-->
133
+ <!--calender-->
134
+ <div id="cal-widget" data-month="<?php echo $queried_month; ?>" data-year="<?php echo $queried_year; ?>" class="right">
135
+ <a class="previous-month" href="#"></a>
136
+ <span><?php echo $display_month[$queried_month] . ' ' . $queried_year; ?></span>
137
+ <a class="next-month" href="#"></a>
138
+ </div>
139
+ <!--/calender-->
140
+ </header>
141
+ <!--/header-->
142
+ <div id="ac-content">
143
+ <?php if ( $steps[0]['reached'] == 0 ) { ?>
144
+ <ul>
145
+ <li><p class="out-of-data">You will see some data here as soon as we have it.</p></li>
146
+ </ul>
147
+ <?php } else { ?>
148
+ <!--stats list-->
149
+ <ul>
150
+ <?php foreach ( $steps as $key => $step ) { ?>
151
+ <li>
152
+ <div class="ac-steps left"><span><?php echo $key + 1; ?>&nbsp;</span><?php echo $step_names[$step['step']]; ?></div>
153
+ <div class="ac-graph left">
154
+ <center><?php echo $step['reached']; ?></center>
155
+ <div class="ac-usr-in" style="width:<?php echo $steps[0]['reached'] == 0 ? 0 : round( $step['reached'] * 100 / $steps[0]['reached'], 0 ); ?>px;">
156
+ <div class="ac-usr-out" style="height:<?php echo round( $step['loss'], 0 ); ?>%"></div>
157
+ </div>
158
+ <?php
159
+ // if on last step, show last 'moved' value i.e. tail of funnel
160
+ if ( $key == count( $steps ) - 1 )
161
+ echo '<center>' . $step['moved'] . '<center>';
162
+ ?>
163
+ </div>
164
+ <div class="ac-stats left"><div>&nbsp;<?php echo round( $step['loss'], 2 ); ?>&nbsp;%</div></div>
165
+ </li>
166
+ <?php } ?>
167
+ </ul>
168
+ <!--stats list-->
169
+ <?php } ?>
170
+ <!--sidebar-->
171
+ <div id="ac-sidebar">
172
+ <div class="ac-notif">
173
+ <div>
174
+ <big>NOTIFICATION!</big>
175
+ <?php echo $message; ?>
176
+ </div>
177
+ </div>
178
+ <div class="ac-side-content">
179
+ <span>>APPX. LOSS</span>
180
+ <p>*based on total monthly sales</p>
181
+ <big><?php echo $approx_loss; ?></big>
182
+ <p class="btm">TOTAL PERCENTAGE <br/>OF ABANDONMENT</p>
183
+ <big class="btm"><?php echo $abandonedment_rate; ?>%</big>
184
+ </div>
185
+ </div>
186
+ <!--sidebar-->
187
+ </div>
188
+ </div>
app/etc/modules/AnattaDesign_AbandonedCarts.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <config>
3
+ <modules>
4
+ <AnattaDesign_AbandonedCarts>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ </AnattaDesign_AbandonedCarts>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>AnattaDesign_AbandonedCarts</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license>GPL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Track abandoned carts &amp; show a funnel report to show statistics</summary>
10
+ <description>Track abandoned carts &amp;amp; show a funnel report to show statistics</description>
11
+ <notes>First version - Track abandoned carts &amp;amp; show a funnel report to show statistics</notes>
12
+ <authors><author><name>Anatta Design</name><user>anattadesign</user><email>nirav@anattadesign.com</email></author></authors>
13
+ <date>2012-12-05</date>
14
+ <time>15:37:55</time>
15
+ <contents><target name="magelocal"><dir name="AnattaDesign"><dir name="AbandonedCarts"><dir name="Block"><file name="Widget.php" hash="c6baf4dc8dc25ed7c62e3b89cc78c413"/></dir><dir name="Helper"><file name="Data.php" hash="093342a0866fc724b4b0e6c545ef177b"/></dir><dir name="Model"><dir name="Checkout"><dir name="Onepage"><file name="Observer.php" hash="e7fdbe25fa84f25b5d1d49913489c147"/></dir></dir><dir name="Mysql4"><dir name="Opstatistics"><file name="Collection.php" hash="66b29da439c196f325c9faec4b171f30"/></dir><file name="Opstatistics.php" hash="9ccaa740ddbfa607204bde0222fceafc"/><dir name="Statistics"><file name="Collection.php" hash="c92997470a39016001c196fa4bf17861"/></dir><file name="Statistics.php" hash="88d17295de3fc05637ac55e71c52a3a3"/></dir><file name="Observer.php" hash="ab8d6551678e9169e80dd947e53d4329"/><file name="Opstatistics.php" hash="f3bfe7b7e44ef33e15877332a767b25a"/><file name="Statistics.php" hash="50a8c9c194a30613cb98471f4a66e7a9"/></dir><dir name="controllers"><file name="WidgetController.php" hash="ca23d690e09435f5f4df54c539dea74b"/></dir><dir name="etc"><file name="config.xml" hash="558f158a47ded67e33e113df97a1ef8a"/></dir><dir name="sql"><dir name="anattadesign_abandonedcarts_setup"><file name="mysql4-install-1.0.php" hash="b235486189e6609d4f9abc82ffae76c7"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="anattadesign_abandonedcarts.xml" hash="c14481626a0c367d974a5660ed930482"/></dir><dir name="template"><dir name="anattadesign"><dir name="abandonedcarts"><file name="widget.phtml" hash="afb7f04d2c91e878b7afed12c5f96966"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="AnattaDesign_AbandonedCarts.xml" hash="fba54c1c1c7b2abd323a56bcdd56be20"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="anattadesign"><dir name="abandonedcarts"><dir name="css"><dir><dir name="images"><file name="ar-lt.jpg" hash="2e4a2506cc63419a0e0c9a41669a8bda"/><file name="ar-rt.jpg" hash="8ef650d1c452ea7a4cc846f0999fddc0"/><file name="logo.jpg" hash="df05a2e01e46a38652d3514046ae30cd"/><file name="notifications-btm.gif" hash="716074a30178e9aca3b1fe0698cfcfb7"/><file name="notifications.gif" hash="343c52ea083df65f1a02c6d7334281c2"/></dir></dir><file name="style.css" hash="9f88676ad1011b2569a1f1c3e08d9297"/></dir></dir></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>5.4.6</max></php></required></dependencies>
18
+ </package>
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/ar-lt.jpg ADDED
Binary file
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/ar-rt.jpg ADDED
Binary file
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/logo.jpg ADDED
Binary file
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/notifications-btm.gif ADDED
Binary file
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/images/notifications.gif ADDED
Binary file
skin/adminhtml/default/default/anattadesign/abandonedcarts/css/style.css ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Abandoned Cart - styles */
2
+ #ac-wrapper{ width: 372px; overflow: hidden; position: relative; left: -7px; }
3
+ #ac-wrapper .left{ float: left;}
4
+ #ac-wrapper .right{ float: right;}
5
+
6
+ /* header */
7
+ #ac-header{ height: 35px; border-bottom: 1px solid #cccccc; overflow:hidden; font-family:"Exo"; font-size: 16px; font-weight: 600; padding: 10px 0 0 0; }
8
+
9
+ #cal-widget { width: auto;}
10
+ #cal-widget a{ width: 11px; height: 17px; display: block; margin: 2px 2px 0px 2px; }
11
+ #cal-widget span{ display: block; float: left;}
12
+ #cal-widget a.previous-month {background: url(images/ar-lt.jpg) no-repeat; float: left}
13
+ #cal-widget a.next-month{ background: url(images/ar-rt.jpg) no-repeat; float: right;}
14
+
15
+ /* content */
16
+ #ac-content { overflow:hidden;}
17
+ #ac-content ul{ list-style: none; padding: 5px 0 0 0; margin: 0; font-family: "Ubuntu"; width: 217px; float: left;}
18
+ #ac-content ul li{ clear: both; padding-top: 5px;}
19
+
20
+ .ac-steps{ font-size: 12px; color: #4d4d4d; width:70px; line-height: 16px; padding-top: 10px;}
21
+ .ac-steps span{ color: #b3b3b3;}
22
+
23
+ .ac-graph{ width: 100px; font-size: 10px;}
24
+ .ac-graph .ac-usr-in{ margin: 0px auto; background: #ff9200; height: 48px; border-radius: 3px;-moz-border-radius: 3px;-webkit-border-radius: 3px; position: relative;}
25
+ .ac-graph .ac-usr-out {background: #000; position: absolute; bottom: 0px; width: 100%; }
26
+ .ac-stats { color: #0071bc; font-size: 12px; padding: 45px 0 0 0; position: relative; }
27
+ .ac-stats div { position: absolute; left: 0; bottom: 0; }
28
+
29
+ /* sidebar */
30
+ #ac-sidebar { float: right; width: 154px; }
31
+ #ac-sidebar .ac-notif { background: url(images/notifications.gif) no-repeat; margin :15px 0 20px 0;}
32
+ #ac-sidebar .ac-notif div{background: url(images/notifications-btm.gif) left bottom no-repeat; width: 118px; min-height: 110px; padding: 21px 25px 20px 15px; }
33
+
34
+ .ac-side-content,.ac-notif { font-family: "Ubuntu"; color: #000000; font-size: 10px;}
35
+ .ac-notif a{ color: #0071bc;}
36
+ .ac-notif a:hover{ text-decoration: none;}
37
+ .ac-notif big{ text-transform: uppercase;}
38
+ .ac-notif p{ padding: 15px 0; margin: 0;}
39
+
40
+ .ac-side-content {}
41
+ .ac-side-content p{ padding: 3px 0 10px 0; margin: 0;}
42
+ .ac-side-content big{ font-size: 20px;font-family: "Ubuntu"; font-weight: 500;}
43
+ .ac-side-content p.btm{ font-size: 11px; text-transform: uppercase; padding: 37px 0 15px 0 ;}
44
+ .ac-side-content big.btm{ font-size: 36px;}
45
+
46
+ .out-of-data { width: 90%; }