├── .gitignore ├── LICENSE ├── README.md ├── Vagrantfile ├── app ├── code │ └── community │ │ └── DEG │ │ └── OrderLifecycle │ │ ├── Helper │ │ └── Data.php │ │ ├── Model │ │ ├── Hooks.php │ │ ├── Lifecycle │ │ │ ├── Event.php │ │ │ └── Event │ │ │ │ ├── Admin │ │ │ │ └── Event.php │ │ │ │ ├── Api │ │ │ │ └── Event.php │ │ │ │ ├── Collection.php │ │ │ │ ├── Factory.php │ │ │ │ └── Frontend │ │ │ │ └── Event.php │ │ ├── Observer.php │ │ ├── System │ │ │ └── Config │ │ │ │ └── Source │ │ │ │ └── Adapter.php │ │ └── Write │ │ │ └── Adapter │ │ │ ├── Factory.php │ │ │ ├── Interface.php │ │ │ ├── Json │ │ │ └── Post.php │ │ │ └── Order │ │ │ └── History.php │ │ ├── Test │ │ ├── Api │ │ │ └── OrderTest.php │ │ └── Model │ │ │ ├── HooksTest.php │ │ │ ├── Lifecycle │ │ │ └── Event │ │ │ │ ├── Admin │ │ │ │ └── EventTest.php │ │ │ │ ├── Api │ │ │ │ └── EventTest.php │ │ │ │ ├── CollectionTest.php │ │ │ │ ├── FactoryTest.php │ │ │ │ └── Frontend │ │ │ │ └── EventTest.php │ │ │ ├── ObserverTest.php │ │ │ └── Write │ │ │ └── Adapter │ │ │ ├── FactoryTest.php │ │ │ ├── Json │ │ │ └── PostTest.php │ │ │ └── Order │ │ │ └── HistoryTest.php │ │ └── etc │ │ ├── config.xml │ │ └── system.xml └── etc │ └── modules │ └── DEG_OrderLifecycle.xml ├── composer.json └── modman /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 DEG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # magento-order-lifecycle 2 | Track everything and anything that is related to an order and write it so that it can be seen in the admin panel. Magento 1.X 3 | 4 | ## Features 5 | This module contains a set of observers to create order lifecycle events. These events will can be written to the order history table or posted to an endpoint using JSON. Refer to this [wiki page](https://github.com/degdigital/magento-order-lifecycle/wiki/Hook-List) for a list of the hooks. 6 | 7 | You can add your own events. Refer to this [wiki page](https://github.com/degdigital/magento-order-lifecycle/wiki/Adding-a-New-Event) 8 | 9 | You can add your own write adapters. Write adapters are used to write or send the event data. Refer to this [wiki page](https://github.com/degdigital/magento-order-lifecycle/wiki/Lifecycle-Write-Adapters) for the existing write adapters. 10 | 11 | ## ToDo 12 | * Create a new view in the admin panel for the lifecycle events. 13 | * Add more hooks and capture more order event data. 14 | 15 | ## Configuration 16 | * System > Configuration > Sales > Order Lifecycle - Defines the event writing adapter. 17 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | # All Vagrant configuration is done here. The most common configuration 6 | # options are documented and commented below. For a complete reference, 7 | # please see the online documentation at vagrantup.com. 8 | 9 | # Every Vagrant virtual environment requires a box to build off of. 10 | config.vm.box = "centos-6-5-x64-virtualbox-php54" 11 | config.vm.box_url = "https://s3.amazonaws.com/magento-hackathon/centos-6-5-x64-virtualbox-php54.box" 12 | config.vm.box_download_checksum_type = "md5" 13 | config.vm.box_download_checksum = "eb0bf40dad1b7976191505c7cd593070-22" 14 | 15 | config.vm.synced_folder "../hackathon", "/var/magento/hackathon/", type: "nfs" 16 | 17 | config.vm.network :private_network, ip: "192.168.33.15" 18 | 19 | config.vm.provider :virtualbox do |vb, override| 20 | vb.name = "magentohackathon" 21 | vb.customize ["modifyvm", :id, "--memory", "2048"] 22 | vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Helper/Data.php: -------------------------------------------------------------------------------- 1 | getDataObject(); 7 | $newStatus = $order->getData('status'); 8 | $oldStatus = $order->getOrigData('status'); 9 | if ($newStatus != $oldStatus) { 10 | $object = new Varien_Object(); 11 | $object->setOldStatus($oldStatus); 12 | $object->setNewStatus($newStatus); 13 | $this->_dispatchEvent('lifecycle_event', $object); 14 | } 15 | } 16 | 17 | public function paymentCaptureLifecyceEvent($event){ 18 | $object = new Varien_Object(); 19 | $object->setMessage('Captured Payment'); 20 | $this->_dispatchEvent('lifecycle_event', $object); 21 | } 22 | 23 | public function paymentRefundLifecyceEvent($event){ 24 | $object = new Varien_Object(); 25 | $object->setMessage('Refunded Order'); 26 | $this->_dispatchEvent('lifecycle_event', $object); 27 | } 28 | 29 | public function invoiceCreatedLifecyceEvent($event){ 30 | $object = new Varien_Object(); 31 | $object->setMessage('Invoice Created'); 32 | $this->_dispatchEvent('lifecycle_event', $object); 33 | } 34 | 35 | public function shippmentCreatedLifecyceEvent($event){ 36 | $object = new Varien_Object(); 37 | $object->setMessage('Shippment Created'); 38 | $this->_dispatchEvent('lifecycle_event', $object); 39 | } 40 | 41 | protected function _dispatchEvent($eventName, $data){ 42 | Mage::dispatchEvent($eventName, array('data_object' => $data)); 43 | } 44 | 45 | 46 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event.php: -------------------------------------------------------------------------------- 1 | setEventType($this->_eventType); 7 | $this->_initData(); 8 | return $this; 9 | } 10 | 11 | public function getFormattedEventData() 12 | { 13 | $formattedEventData = ''; 14 | foreach ($this->getData() as $key => $value) { 15 | $formattedEventData .= $key .': '. $value . '
'; 16 | } 17 | 18 | return $formattedEventData; 19 | } 20 | 21 | abstract protected function _initData(); 22 | 23 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event/Admin/Event.php: -------------------------------------------------------------------------------- 1 | getUser(); 11 | $this->setUserId($admin->getUserId()); 12 | $this->setUsername($admin->getUsername()); 13 | $this->setEmail($admin->getEmail()); 14 | $this->setFirstname($admin->getFirstname()); 15 | $this->setLastname($admin->getLastname()); 16 | 17 | $adminSessionQuote = Mage::getSingleton('adminhtml/session_quote'); 18 | if ($adminSessionQuote->getReordered()) { 19 | $reorderId = $adminSessionQuote->getReordered(); 20 | $this->setReorderPreviousOrderId($reorderId); 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event/Api/Event.php: -------------------------------------------------------------------------------- 1 | getUser(); 10 | $this->setUserId($apiUser->getUserId()); 11 | $this->setUsername($apiUser->getUsername()); 12 | $this->setEmail($apiUser->getEmail()); 13 | $this->setFirstname($apiUser->getFirstname()); 14 | $this->setLastname($apiUser->getLastname()); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event/Collection.php: -------------------------------------------------------------------------------- 1 | _events[] = $event; 11 | } 12 | 13 | public function getEvents(){ 14 | return $this->_events; 15 | } 16 | 17 | public function resetEvents(){ 18 | $this->_events = array(); 19 | return $this; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event/Factory.php: -------------------------------------------------------------------------------- 1 | getAdapter() != null; 6 | if ($apiRunning) { 7 | return Mage::getModel('deg_orderlifecycle/lifecycle_event_api_event')->initDataObject(); 8 | }else if (Mage::app()->getStore()->isAdmin()) { 9 | return Mage::getModel('deg_orderlifecycle/lifecycle_event_admin_event')->initDataObject(); 10 | } 11 | 12 | return Mage::getModel('deg_orderlifecycle/lifecycle_event_frontend_event')->initDataObject(); 13 | } 14 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Lifecycle/Event/Frontend/Event.php: -------------------------------------------------------------------------------- 1 | getRemoteAddr(); 10 | $this->setRemoteIp($remoteIp); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Observer.php: -------------------------------------------------------------------------------- 1 | getEventDataObject(); 7 | $eventData = $event->getDataObject(); 8 | $lifecycleEvent->addData($eventData->getData()); 9 | $collection = Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 10 | if (!$collection){ 11 | $collection = Mage::getModel('deg_orderlifecycle/lifecycle_event_collection'); 12 | } 13 | $collection->addEvent($lifecycleEvent); 14 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 15 | Mage::register(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION, $collection); 16 | } 17 | 18 | public function orderSavedEventFlush($event){ 19 | $adapter = Mage::getSingleton('deg_orderlifecycle/write_adapter_factory')->getWriteAdapter(); 20 | $order = $event->getDataObject(); 21 | $adapter->flush($order, 'order'); 22 | } 23 | 24 | public function invoiceSavedEventFlush($event){ 25 | $adapter = Mage::getSingleton('deg_orderlifecycle/write_adapter_factory')->getWriteAdapter(); 26 | $order = $event->getDataObject()->getOrder(); 27 | $adapter->flush($order, 'invoice'); 28 | } 29 | 30 | public function paymentSavedEventFlush($event){ 31 | $adapter = Mage::getSingleton('deg_orderlifecycle/write_adapter_factory')->getWriteAdapter(); 32 | $order = $event->getDataObject()->getOrder(); 33 | $adapter->flush($order, 'payment'); 34 | } 35 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/System/Config/Source/Adapter.php: -------------------------------------------------------------------------------- 1 | DEG_OrderLifecycle_Model_Write_Adapter_Order_History::ADAPTER_ORDER_HISTORY, 'label'=>Mage::helper('deg_orderlifecycle')->__('Order History')), 15 | array('value' => DEG_OrderLifecycle_Model_Write_Adapter_Json_Post::ADAPTER_JSON_POST, 'label'=>Mage::helper('deg_orderlifecycle')->__('JSON Post')), 16 | ); 17 | } 18 | 19 | /** 20 | * Get options in "key-value" format 21 | * 22 | * @return array 23 | */ 24 | public function toArray() 25 | { 26 | return array( 27 | DEG_OrderLifecycle_Model_Write_Adapter_Order_History::ADAPTER_ORDER_HISTORY => Mage::helper('deg_orderlifecycle')->__('Order History'), 28 | DEG_OrderLifecycle_Model_Write_Adapter_Json_Post::ADAPTER_JSON_POST => Mage::helper('deg_orderlifecycle')->__('JSON Post'), 29 | ); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Write/Adapter/Factory.php: -------------------------------------------------------------------------------- 1 | _getUrl(); 12 | foreach ($collection->getEvents() as $event) { 13 | $jsonBody = $this->formatEventData($event); 14 | 15 | $options = array( 16 | 'http' => array( 17 | 'header' => "Content-type: application/json\r\n", 18 | 'method' => 'POST', 19 | 'content' => $jsonBody, 20 | ), 21 | ); 22 | $context = $this->_createContext($options); 23 | $result = $this->_sendRequest($url, $context); 24 | } 25 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 26 | } 27 | } 28 | 29 | protected function _getUrl(){ 30 | return Mage::getStoreConfig('sales/order_lifecycle/post_url'); 31 | } 32 | 33 | protected function _createContext($options){ 34 | return stream_context_create($options); 35 | } 36 | 37 | protected function _sendRequest($url, $context){ 38 | return file_get_contents($url, false, $context); 39 | } 40 | 41 | public function formatEventData(DEG_OrderLifecycle_Model_Lifecycle_Event $event){ 42 | return json_encode($event->getData()); 43 | } 44 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Model/Write/Adapter/Order/History.php: -------------------------------------------------------------------------------- 1 | getEvents() as $event) { 12 | $comment = $this->formatEventData($event); 13 | $history = Mage::getModel('sales/order_status_history'); 14 | $history->setParentId($order->getId()); 15 | $history->setStatus($order->getStatus()); 16 | $history->setComment($comment); 17 | $history->setIsCustomerNotified(0); 18 | $history->setIsVisibleOnFront(0); 19 | $history->setEntityName($historyEntity); 20 | $history->save(); 21 | } 22 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 23 | } 24 | } 25 | 26 | public function formatEventData(DEG_OrderLifecycle_Model_Lifecycle_Event $event){ 27 | $formattedEventData = ''; 28 | foreach ($event->getData() as $key => $value) { 29 | $formattedEventData .= $key .': '. $value . '
'; 30 | } 31 | 32 | return $formattedEventData; 33 | } 34 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Api/OrderTest.php: -------------------------------------------------------------------------------- 1 | login($apiuser, $apikey); //we do login 13 | } catch (Exception $e) { //while an error has occured 14 | echo "==> Error: " . $e->getMessage(); //we print this 15 | } 16 | return $sess_id; 17 | } 18 | 19 | public function testHold(){ 20 | $session = $this->_prepare(); 21 | $client = new SoapClient("http://hackathon.dev/api/soap/?wsdl"); //soap handle 22 | try { 23 | print_r($client->call($session, 'sales_order.hold', '100000094')); 24 | } catch (Exception $e) { //while an error has occured 25 | echo "==> Error: " . $e->getMessage(); //we print this 26 | } 27 | 28 | } 29 | 30 | public function testUnHold(){ 31 | $session = $this->_prepare(); 32 | $client = new SoapClient("http://hackathon.dev/api/soap/?wsdl"); //soap handle 33 | try { 34 | print_r($client->call($session, 'sales_order.unhold', '100000094')); 35 | } catch (Exception $e) { //while an error has occured 36 | echo "==> Error: " . $e->getMessage(); //we print this 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/HooksTest.php: -------------------------------------------------------------------------------- 1 | setMessage('Shippment Created'); 9 | $observer = $this->mockModel('deg_orderlifecycle/hooks',array('_dispatchEvent')); 10 | $observer->expects($this->any())->method('_dispatchEvent')->with('lifecycle_event', $expectedValue); 11 | $observerObject = new Varien_Event_Observer(); 12 | $observer->shippmentCreatedLifecyceEvent($observerObject); 13 | } 14 | 15 | public function testInvoiceCreatedLifecyceEvent(){ 16 | $expectedValue = new Varien_Object(); 17 | $expectedValue->setMessage('Invoice Created'); 18 | $observer = $this->mockModel('deg_orderlifecycle/hooks',array('_dispatchEvent')); 19 | $observer->expects($this->any())->method('_dispatchEvent')->with('lifecycle_event', $expectedValue); 20 | $observerObject = new Varien_Event_Observer(); 21 | $observer->invoiceCreatedLifecyceEvent($observerObject); 22 | } 23 | 24 | public function testPaymentRefundLifecyceEvent(){ 25 | $expectedValue = new Varien_Object(); 26 | $expectedValue->setMessage('Refunded Order'); 27 | $observer = $this->mockModel('deg_orderlifecycle/hooks',array('_dispatchEvent')); 28 | $observer->expects($this->any())->method('_dispatchEvent')->with('lifecycle_event', $expectedValue); 29 | $observerObject = new Varien_Event_Observer(); 30 | $observer->paymentRefundLifecyceEvent($observerObject); 31 | } 32 | 33 | public function testPaymentCapturedLifecyceEvent(){ 34 | $expectedValue = new Varien_Object(); 35 | $expectedValue->setMessage('Captured Payment'); 36 | $observer = $this->mockModel('deg_orderlifecycle/hooks',array('_dispatchEvent')); 37 | $observer->expects($this->any())->method('_dispatchEvent')->with('lifecycle_event', $expectedValue); 38 | $observerObject = new Varien_Event_Observer(); 39 | $observer->paymentCaptureLifecyceEvent($observerObject); 40 | } 41 | 42 | public function testOrderAfterSaveLifecycleEvent(){ 43 | 44 | 45 | $order = $this->mockModel('sales/order', array('getData','getOrigData')); 46 | $order->expects($this->any())->method('getData')->will($this->returnValue('hold')); 47 | $order->expects($this->any())->method('getOrigData')->will($this->returnValue('new')); 48 | 49 | $expectedValue = new Varien_Object(); 50 | $expectedValue->setOldStatus('new'); 51 | $expectedValue->setNewStatus('hold'); 52 | 53 | $observer = $this->mockModel('deg_orderlifecycle/hooks',array('_dispatchEvent')); 54 | $observer->expects($this->any())->method('_dispatchEvent')->with('lifecycle_event', $expectedValue); 55 | $observerObject = new Varien_Event_Observer(); 56 | $observerObject->setDataObject($order); 57 | 58 | $observer->orderAfterSaveLifecycleEvent($observerObject); 59 | } 60 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Lifecycle/Event/Admin/EventTest.php: -------------------------------------------------------------------------------- 1 | setCurrentStore(0); 8 | $adminUser = new Varien_Object(); 9 | $adminUser->setUserId(1); 10 | $adminUser->setUsername('username'); 11 | $adminUser->setEmail('email'); 12 | $adminUser->setFirstname('firstname'); 13 | $adminUser->setLastname('lastname'); 14 | 15 | $adminSessionMock = $this->getModelMockBuilder('admin/session') 16 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 17 | ->setMethods(array('getUser')) // Enables original methods usage, because by default it overrides all methods 18 | ->getMock(); 19 | $adminSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($adminUser)); 20 | $this->replaceByMock('singleton', 'admin/session', $adminSessionMock); 21 | 22 | $adminSessionQuoteMock = $this->getModelMockBuilder('adminhtml/session_quote') 23 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 24 | ->setMethods(null) // Enables original methods usage, because by default it overrides all methods 25 | ->getMock(); 26 | $this->replaceByMock('singleton', 'adminhtml/session_quote', $adminSessionQuoteMock); 27 | 28 | $adminEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 29 | $adminEvent->initDataObject(); 30 | 31 | $this->assertEquals(1,$adminEvent->getUserId()); 32 | $this->assertEquals('username',$adminEvent->getUsername()); 33 | $this->assertEquals('email',$adminEvent->getEmail()); 34 | } 35 | 36 | public function testInitDataObjectReorder() 37 | { 38 | $this->setCurrentStore(0); 39 | $adminUser = new Varien_Object(); 40 | $adminUser->setUserId(1); 41 | $adminUser->setUsername('username'); 42 | $adminUser->setEmail('email'); 43 | $adminUser->setFirstname('firstname'); 44 | $adminUser->setLastname('lastname'); 45 | 46 | $adminSessionMock = $this->getModelMockBuilder('admin/session') 47 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 48 | ->setMethods(array('getUser')) // Enables original methods usage, because by default it overrides all methods 49 | ->getMock(); 50 | $adminSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($adminUser)); 51 | $this->replaceByMock('singleton', 'admin/session', $adminSessionMock); 52 | 53 | $adminSessionQuoteMock = $this->getModelMockBuilder('adminhtml/session_quote') 54 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 55 | ->setMethods(array('getReordered')) // Enables original methods usage, because by default it overrides all methods 56 | ->getMock(); 57 | $adminSessionQuoteMock->expects($this->any())->method('getReordered')->will($this->returnValue('1234')); 58 | $this->replaceByMock('singleton', 'adminhtml/session_quote', $adminSessionQuoteMock); 59 | 60 | $adminEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 61 | $adminEvent->initDataObject(); 62 | 63 | $this->assertEquals('1234',$adminEvent->getReorderPreviousOrderId()); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Lifecycle/Event/Api/EventTest.php: -------------------------------------------------------------------------------- 1 | setCurrentStore(0); 8 | $adminUser = new Varien_Object(); 9 | $adminUser->setUserId(1); 10 | $adminUser->setUsername('username'); 11 | $adminUser->setEmail('email'); 12 | $adminUser->setFirstname('firstname'); 13 | $adminUser->setLastname('lastname'); 14 | 15 | $apiSessionMock = $this->getModelMockBuilder('api/session') 16 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 17 | ->setMethods(array('getUser')) // Enables original methods usage, because by default it overrides all methods 18 | ->getMock(); 19 | $apiSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($adminUser)); 20 | $this->replaceByMock('singleton', 'api/session', $apiSessionMock); 21 | 22 | $apiEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Api_Event(); 23 | $apiEvent->initDataObject(); 24 | 25 | $this->assertEquals(1,$apiEvent->getUserId()); 26 | $this->assertEquals('username',$apiEvent->getUsername()); 27 | $this->assertEquals('email',$apiEvent->getEmail()); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Lifecycle/Event/CollectionTest.php: -------------------------------------------------------------------------------- 1 | setTestValue('test1'); 9 | $event2 = new Varien_Object(); 10 | $event2->setTestValue('test2'); 11 | $collection = new DEG_OrderLifecycle_Model_Lifecycle_Event_Collection(); 12 | $this->assertEquals(0, sizeof($collection->getEvents())); 13 | $collection->addEvent($event1); 14 | $collection->addEvent($event2); 15 | $this->assertEquals(2, sizeof($collection->getEvents())); 16 | } 17 | 18 | public function testResetEvents(){ 19 | $event1 = new Varien_Object(); 20 | $event1->setTestValue('test1'); 21 | $event2 = new Varien_Object(); 22 | $event2->setTestValue('test2'); 23 | $collection = new DEG_OrderLifecycle_Model_Lifecycle_Event_Collection(); 24 | $this->assertEquals(0, sizeof($collection->getEvents())); 25 | $collection->addEvent($event1); 26 | $collection->addEvent($event2); 27 | $this->assertEquals(2, sizeof($collection->getEvents())); 28 | $collection->resetEvents(); 29 | $this->assertEquals(0, sizeof($collection->getEvents())); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Lifecycle/Event/FactoryTest.php: -------------------------------------------------------------------------------- 1 | setCurrentStore(1); 8 | $factory = new DEG_OrderLifecycle_Model_Lifecycle_Event_Factory(); 9 | $eventObject = $factory->getEventDataObject(); 10 | $this->assertInstanceOf('DEG_OrderLifecycle_Model_Lifecycle_Event_Frontend_Event',$eventObject); 11 | } 12 | 13 | public function testGetEventDataObjectAdmin() 14 | { 15 | $this->setCurrentStore(0); 16 | $adminUser = new Varien_Object(); 17 | $adminUser->setId(1); 18 | $adminUser->setUsername('username'); 19 | $adminUser->setEmail('email'); 20 | $adminUser->setFirstname('firstname'); 21 | $adminUser->setLastname('lastname'); 22 | 23 | $adminSessionMock = $this->getModelMockBuilder('admin/session') 24 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 25 | ->setMethods(array('getUser')) // Enables original methods usage, because by default it overrides all methods 26 | ->getMock(); 27 | $adminSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($adminUser)); 28 | $this->replaceByMock('singleton', 'admin/session', $adminSessionMock); 29 | 30 | $adminSessionQuoteMock = $this->getModelMockBuilder('adminhtml/session_quote') 31 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 32 | ->setMethods(null) // Enables original methods usage, because by default it overrides all methods 33 | ->getMock(); 34 | $this->replaceByMock('singleton', 'adminhtml/session_quote', $adminSessionQuoteMock); 35 | 36 | $factory = new DEG_OrderLifecycle_Model_Lifecycle_Event_Factory(); 37 | $eventObject = $factory->getEventDataObject(); 38 | $this->assertInstanceOf('DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event',$eventObject); 39 | } 40 | 41 | public function testGetEventDataObjectApi() 42 | { 43 | $this->setCurrentStore(0); 44 | $adminUser = new Varien_Object(); 45 | $adminUser->setUserId(1); 46 | $adminUser->setUsername('username'); 47 | $adminUser->setEmail('email'); 48 | $adminUser->setFirstname('firstname'); 49 | $adminUser->setLastname('lastname'); 50 | 51 | $apiSessionMock = $this->getModelMockBuilder('api/session') 52 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 53 | ->setMethods(array('getUser')) // Enables original methods usage, because by default it overrides all methods 54 | ->getMock(); 55 | $apiSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($adminUser)); 56 | $this->replaceByMock('singleton', 'api/session', $apiSessionMock); 57 | 58 | $apiServerMock = $this->getModelMock('api/server', array('getAdapter')); 59 | $apiServerMock->expects($this->any())->method('getAdapter')->will($this->returnValue('api')); 60 | $this->replaceByMock('singleton', 'api/server', $apiServerMock); 61 | 62 | 63 | $factory = new DEG_OrderLifecycle_Model_Lifecycle_Event_Factory(); 64 | $eventObject = $factory->getEventDataObject(); 65 | $this->assertInstanceOf('DEG_OrderLifecycle_Model_Lifecycle_Event_Api_Event',$eventObject); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Lifecycle/Event/Frontend/EventTest.php: -------------------------------------------------------------------------------- 1 | getHelperMock('core/http', array('getRemoteAddr')); 8 | $helper->expects($this->once())->method('getRemoteAddr')->will($this->returnValue('127.0.0.1')); 9 | $this->replaceByMock('helper', 'core/http', $helper); 10 | 11 | $frontendEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Frontend_Event(); 12 | $frontendEvent->initDataObject(); 13 | 14 | $this->assertEquals('Frontend',$frontendEvent->getEventType()); 15 | $this->assertEquals('127.0.0.1',$frontendEvent->getRemoteIp()); 16 | } 17 | 18 | 19 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/ObserverTest.php: -------------------------------------------------------------------------------- 1 | mockModel('deg_orderlifecycle/write_adapter_order_history', array('flush')); 10 | $history->expects($this->once())->method('flush')->with($this->equalTo($order)); 11 | 12 | $factory = $this->mockModel('deg_orderlifecycle/write_adapter_factory', array('getWriteAdapter')); 13 | $factory->expects($this->once())->method('getWriteAdapter')->will($this->returnValue($history)); 14 | $this->replaceByMock('model', 'deg_orderlifecycle/write_adapter_factory', $factory); 15 | 16 | $observerObject = new Varien_Event_Observer(); 17 | $observerObject->setDataObject($order); 18 | 19 | $observer = new DEG_OrderLifecycle_Model_Observer(); 20 | $observer->orderSavedEventFlush($observerObject); 21 | } 22 | 23 | public function testInvoiceSavedEventFlush(){ 24 | $order = Mage::getModel('sales/order'); 25 | $invoice = Mage::getModel('sales/order_invoice'); 26 | $invoice->setOrder($order); 27 | $history = $this->mockModel('deg_orderlifecycle/write_adapter_order_history', array('flush')); 28 | $history->expects($this->once())->method('flush')->with($this->equalTo($order)); 29 | 30 | $factory = $this->mockModel('deg_orderlifecycle/write_adapter_factory', array('getWriteAdapter')); 31 | $factory->expects($this->once())->method('getWriteAdapter')->will($this->returnValue($history)); 32 | $this->replaceByMock('model', 'deg_orderlifecycle/write_adapter_factory', $factory); 33 | 34 | $observerObject = new Varien_Event_Observer(); 35 | $observerObject->setDataObject($invoice); 36 | 37 | $observer = new DEG_OrderLifecycle_Model_Observer(); 38 | $observer->invoiceSavedEventFlush($observerObject); 39 | } 40 | 41 | 42 | public function testPaymentSavedEventFlush(){ 43 | $order = Mage::getModel('sales/order'); 44 | $payment = Mage::getModel('sales/order_payment'); 45 | $payment->setOrder($order); 46 | $history = $this->mockModel('deg_orderlifecycle/write_adapter_order_history', array('flush')); 47 | $history->expects($this->once())->method('flush')->with($this->equalTo($order)); 48 | 49 | $factory = $this->mockModel('deg_orderlifecycle/write_adapter_factory', array('getWriteAdapter')); 50 | $factory->expects($this->once())->method('getWriteAdapter')->will($this->returnValue($history)); 51 | $this->replaceByMock('model', 'deg_orderlifecycle/write_adapter_factory', $factory); 52 | 53 | $observerObject = new Varien_Event_Observer(); 54 | $observerObject->setDataObject($payment); 55 | 56 | $observer = new DEG_OrderLifecycle_Model_Observer(); 57 | $observer->paymentSavedEventFlush($observerObject); 58 | } 59 | 60 | 61 | public function testLifecycleEventToRegistryNoCollection(){ 62 | $user = new Mage_Admin_Model_User(); 63 | 64 | $adminSessionMock = $this->getModelMockBuilder('admin/session') 65 | ->disableOriginalConstructor() 66 | ->setMethods(array('getUser')) 67 | ->getMock(); 68 | $adminSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($user)); 69 | $this->replaceByMock('singleton', 'admin/session', $adminSessionMock); 70 | 71 | $adminSessionQuoteMock = $this->getModelMockBuilder('adminhtml/session_quote') 72 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 73 | ->setMethods(null) // Enables original methods usage, because by default it overrides all methods 74 | ->getMock(); 75 | $this->replaceByMock('singleton', 'adminhtml/session_quote', $adminSessionQuoteMock); 76 | 77 | $event = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 78 | $observerObject = new Varien_Event_Observer(); 79 | $observerObject->setDataObject($event); 80 | 81 | $collection = Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 82 | $this->assertNull($collection); 83 | $observer = new DEG_OrderLifecycle_Model_Observer(); 84 | $observer->lifecycleEventToRegistry($observerObject); 85 | $collection = Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 86 | $this->assertNotNull($collection); 87 | } 88 | 89 | public function testLifecycleEventToRegistryExistingCollection(){ 90 | 91 | $user = new Mage_Admin_Model_User(); 92 | 93 | $adminSessionMock = $this->getModelMockBuilder('admin/session') 94 | ->disableOriginalConstructor() 95 | ->setMethods(array('getUser')) 96 | ->getMock(); 97 | $adminSessionMock->expects($this->any())->method('getUser')->will($this->returnValue($user)); 98 | $this->replaceByMock('singleton', 'admin/session', $adminSessionMock); 99 | 100 | $adminSessionQuoteMock = $this->getModelMockBuilder('adminhtml/session_quote') 101 | ->disableOriginalConstructor() // This one removes session_start and other methods usage 102 | ->setMethods(null) // Enables original methods usage, because by default it overrides all methods 103 | ->getMock(); 104 | $this->replaceByMock('singleton', 'adminhtml/session_quote', $adminSessionQuoteMock); 105 | 106 | $event = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 107 | $observerObject = new Varien_Event_Observer(); 108 | $observerObject->setDataObject($event); 109 | $collection = new DEG_OrderLifecycle_Model_Lifecycle_Event_Collection(); 110 | $collection->addEvent($event); 111 | Mage::register(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION, $collection); 112 | $observer = new DEG_OrderLifecycle_Model_Observer(); 113 | $observer->lifecycleEventToRegistry($observerObject); 114 | $collection = Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 115 | $this->assertEquals(2, sizeof($collection->getEvents())); 116 | } 117 | 118 | public function tearDown(){ 119 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Write/Adapter/FactoryTest.php: -------------------------------------------------------------------------------- 1 | getWriteAdapter(); 9 | $this->assertTrue($adapter instanceof DEG_OrderLifecycle_Model_Write_Adapter_Order_History); 10 | 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Write/Adapter/Json/PostTest.php: -------------------------------------------------------------------------------- 1 | array( 11 | 'header' => "Content-type: application/json\r\n", 12 | 'method' => 'POST', 13 | 'content' => '{key:value}', 14 | ), 15 | ); 16 | 17 | $event1 = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 18 | $collection = new DEG_OrderLifecycle_Model_Lifecycle_Event_Collection(); 19 | $collection->addEvent($event1); 20 | 21 | Mage::register(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION, $collection); 22 | $adapter = $this->mockModel('deg_orderlifecycle/write_adapter_json_post', array('_getUrl','_sendRequest', '_createContext', 'formatEventData')); 23 | $adapter->expects($this->once())->method('_getUrl')->will($this->returnValue('http://www.example.com')); 24 | $adapter->expects($this->once())->method('_createContext')->with($this->equalTo($options)); 25 | $adapter->expects($this->once())->method('_sendRequest')->with($this->equalTo('http://www.example.com')); 26 | $adapter->expects($this->once())->method('formatEventData')->will($this->returnValue('{key:value}')); 27 | 28 | 29 | $order = $this->mockModel('sales/order',array('getStatus','getId')); 30 | $order->expects($this->any())->method('getStatus')->will($this->returnValue('Complete')); 31 | $order->expects($this->any())->method('getId')->will($this->returnValue(12)); 32 | 33 | $adapter->flush($order->getMockInstance(), 'order'); 34 | 35 | $this->assertNull(Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION)); 36 | 37 | } 38 | 39 | public function testFormatEventData() 40 | { 41 | $adapter = new DEG_OrderLifecycle_Model_Write_Adapter_Order_History(); 42 | $adminEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 43 | $adminEvent->setUsername('name'); 44 | $adminEvent->setEmail('email'); 45 | $formattedData = $adapter->formatEventData($adminEvent); 46 | $this->assertEquals($formattedData, 'username: name
email: email
'); 47 | } 48 | 49 | public function tearDown(){ 50 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 51 | 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/Test/Model/Write/Adapter/Order/HistoryTest.php: -------------------------------------------------------------------------------- 1 | addEvent($event1); 10 | 11 | Mage::register(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION, $collection); 12 | $adapter = new DEG_OrderLifecycle_Model_Write_Adapter_Order_History(); 13 | 14 | $order = $this->mockModel('sales/order',array('getStatus','getId')); 15 | $order->expects($this->any())->method('getStatus')->will($this->returnValue('Complete')); 16 | $order->expects($this->any())->method('getId')->will($this->returnValue(12)); 17 | 18 | 19 | $history = $this->mockModel('sales/order_status_history',array('setParentId','setStatus','setComment','setIsCustomerNotified','setIsVisibleOnFront','setEntityName','save')); 20 | $history->expects($this->once())->method('setParentId')->with($this->equalTo(12)); 21 | $history->expects($this->once())->method('setStatus')->with($this->equalTo('Complete')); 22 | $history->expects($this->once())->method('setComment')->with($this->equalTo('')); 23 | $history->expects($this->once())->method('setIsCustomerNotified')->with($this->equalTo(0)); 24 | $history->expects($this->once())->method('setIsVisibleOnFront')->with($this->equalTo(0)); 25 | $history->expects($this->once())->method('setEntityName')->with($this->equalTo('order')); 26 | $history->expects($this->once())->method('save'); 27 | $this->replaceByMock('model', 'sales/order_status_history', $history); 28 | 29 | $adapter->flush($order->getMockInstance(), 'order'); 30 | 31 | $this->assertNull(Mage::registry(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION)); 32 | 33 | } 34 | 35 | public function testFormatEventData() 36 | { 37 | $adapter = new DEG_OrderLifecycle_Model_Write_Adapter_Order_History(); 38 | $adminEvent = new DEG_OrderLifecycle_Model_Lifecycle_Event_Admin_Event(); 39 | $adminEvent->setUsername('name'); 40 | $adminEvent->setEmail('email'); 41 | $formattedData = $adapter->formatEventData($adminEvent); 42 | $this->assertEquals($formattedData, 'username: name
email: email
'); 43 | } 44 | 45 | public function tearDown(){ 46 | Mage::unregister(DEG_OrderLifecycle_Model_Lifecycle_Event_Collection::REGISTRY_LIFECYCLE_EVENT_COLLECTION); 47 | 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1.0.0 6 | 7 | 8 | 9 | 10 | 11 | DEG_OrderLifecycle_Helper 12 | 13 | 14 | 15 | 16 | DEG_OrderLifecycle_Model 17 | 18 | 19 | 20 | 21 | 22 | 23 | deg_orderlifecycle/observer 24 | lifecycleEventToRegistry 25 | 26 | 27 | 28 | 29 | 30 | 31 | deg_orderlifecycle/observer 32 | orderSavedEventFlush 33 | 34 | 35 | 36 | 37 | 38 | 39 | deg_orderlifecycle/observer 40 | invoiceSavedEventFlush 41 | 42 | 43 | 44 | 45 | 46 | 47 | deg_orderlifecycle/observer 48 | paymentSavedEventFlush 49 | 50 | 51 | 52 | 53 | 54 | 55 | deg_orderlifecycle/hooks 56 | orderAfterSaveLifecycleEvent 57 | 58 | 59 | 60 | 61 | 62 | 63 | deg_orderlifecycle/hooks 64 | paymentCaptureLifecyceEvent 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | deg_orderlifecycle/hooks 73 | paymentRefundLifecyceEvent 74 | 75 | 76 | 77 | 78 | 79 | 80 | deg_orderlifecycle/hooks 81 | invoiceCreatedLifecyceEvent 82 | 83 | 84 | 85 | 86 | 87 | 88 | deg_orderlifecycle/hooks 89 | shippmentCreatedLifecyceEvent 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | deg_orderlifecycle/write_adapter_order_history 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /app/code/community/DEG/OrderLifecycle/etc/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | text 11 | 1000 12 | 1 13 | 1 14 | 1 15 | 16 | 17 | 18 | Controls how/where the event is written. 19 | 10 20 | select 21 | deg_orderlifecycle/system_config_source_adapter 22 | 1 23 | 1 24 | 1 25 | 26 | 27 | 28 | 20 29 | text 30 | 1 31 | 1 32 | 1 33 | 34 | deg_orderlifecycle/write_adapter_json_post 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/etc/modules/DEG_OrderLifecycle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "degdigital/magento-order-lifecycle", 3 | "type": "magento-module", 4 | "description": "Interface for adding data that pertains to the lifecycle of an order and its children.", 5 | "homepage": "https://github.com/degdigital/magento-order-lifecycle", 6 | "require": { 7 | "php": ">=5.3", 8 | "magento-hackathon/magento-composer-installer": "*", 9 | "ecomdev/ecomdev_phpunit": "*" 10 | }, 11 | "repositories": [ 12 | { 13 | "type": "composer", 14 | "url": "http://packages.firegento.com" 15 | } 16 | ], 17 | "extra": { 18 | "magento-root-dir": "../hackathon", 19 | "magento-deploystrategy": "symlink" 20 | } 21 | } -------------------------------------------------------------------------------- /modman: -------------------------------------------------------------------------------- 1 | app/code/community/DEG/OrderLifecycle app/code/community/DEG/OrderLifecycle 2 | app/etc/modules/DEG_OrderLifecycle.xml app/etc/modules/DEG_OrderLifecycle.xml 3 | --------------------------------------------------------------------------------