├── LICENSE.txt
├── aoe-logo.png
├── skin
└── adminhtml
│ └── default
│ └── default
│ └── css
│ └── aoe_fraudmanager.css
├── app
├── code
│ └── local
│ │ └── Aoe
│ │ └── FraudManager
│ │ ├── Model
│ │ ├── Config
│ │ │ └── Source
│ │ │ │ └── Order
│ │ │ │ ├── HoldStatuses.php
│ │ │ │ └── HoldStatusesNone.php
│ │ ├── HoldRule.php
│ │ ├── BlacklistRule.php
│ │ ├── Form
│ │ │ └── Element
│ │ │ │ ├── Renderer
│ │ │ │ ├── Conditions.php
│ │ │ │ ├── Newchild.php
│ │ │ │ └── Editable.php
│ │ │ │ └── Select.php
│ │ ├── Rule
│ │ │ ├── Condition
│ │ │ │ ├── Order
│ │ │ │ │ ├── BillingAddress
│ │ │ │ │ │ └── Attribute.php
│ │ │ │ │ ├── ShippingAddress
│ │ │ │ │ │ └── Attribute.php
│ │ │ │ │ ├── Item
│ │ │ │ │ │ ├── Combine.php
│ │ │ │ │ │ ├── Attribute.php
│ │ │ │ │ │ └── Found.php
│ │ │ │ │ ├── Address
│ │ │ │ │ │ ├── Attribute.php
│ │ │ │ │ │ └── Compare.php
│ │ │ │ │ └── Attribute.php
│ │ │ │ ├── Root.php
│ │ │ │ ├── Interface.php
│ │ │ │ ├── Abstract.php
│ │ │ │ ├── Attribute.php
│ │ │ │ └── Combine.php
│ │ │ └── Abstract.php
│ │ └── Observer.php
│ │ ├── controllers
│ │ ├── FraudManager
│ │ │ ├── HoldRuleController.php
│ │ │ └── BlacklistRuleController.php
│ │ └── Sales
│ │ │ └── OrderController.php
│ │ ├── Helper
│ │ ├── Data.php
│ │ ├── Condition.php
│ │ ├── HoldRule.php
│ │ ├── BlacklistRule.php
│ │ ├── FraudFlag.php
│ │ └── AbstractRule.php
│ │ ├── Resource
│ │ ├── HoldRule
│ │ │ └── Collection.php
│ │ ├── BlacklistRule
│ │ │ └── Collection.php
│ │ ├── HoldRule.php
│ │ ├── BlacklistRule.php
│ │ ├── Abstract.php
│ │ └── Collection
│ │ │ └── Abstract.php
│ │ ├── sql
│ │ └── Aoe_FraudManager
│ │ │ ├── install-0.1.0.php
│ │ │ └── upgrade-0.1.0-0.2.0.php
│ │ ├── Test
│ │ └── Model
│ │ │ ├── HoldRule.php
│ │ │ └── BlacklistRule.php
│ │ ├── Controller
│ │ └── RuleController.php
│ │ └── etc
│ │ ├── adminhtml.xml
│ │ ├── config.xml
│ │ └── system.xml
├── locale
│ └── en_US
│ │ ├── template
│ │ └── email
│ │ │ └── aoe_fraudmanager
│ │ │ └── notification_email.txt
│ │ └── Aoe_FraudManager.csv
├── etc
│ └── modules
│ │ └── Aoe_FraudManager.xml
└── design
│ └── adminhtml
│ └── default
│ └── default
│ ├── template
│ └── aoe_fraudmanager
│ │ ├── rule
│ │ ├── fieldset.phtml
│ │ ├── form.phtml
│ │ └── js.phtml
│ │ └── sales
│ │ └── order
│ │ └── view
│ │ └── info.phtml
│ └── layout
│ └── Aoe_FraudManager.xml
├── modman
├── README.md
├── composer.json
├── .travis.yml
├── phpcs.xml
└── run_tests.sh
/LICENSE.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AOEpeople/Aoe_FraudManager/HEAD/LICENSE.txt
--------------------------------------------------------------------------------
/aoe-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AOEpeople/Aoe_FraudManager/HEAD/aoe-logo.png
--------------------------------------------------------------------------------
/skin/adminhtml/default/default/css/aoe_fraudmanager.css:
--------------------------------------------------------------------------------
1 | #order_status_fraud {
2 | color: #FF0000;
3 | font-weight: bold;
4 | text-transform: uppercase;
5 | }
6 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Config/Source/Order/HoldStatuses.php:
--------------------------------------------------------------------------------
1 | _setResourceModel('Aoe_FraudManager/HoldRule', 'Aoe_FraudManager/HoldRule_Collection');
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/BlacklistRule.php:
--------------------------------------------------------------------------------
1 | _setResourceModel('Aoe_FraudManager/BlacklistRule', 'Aoe_FraudManager/BlacklistRule_Collection');
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/controllers/FraudManager/HoldRuleController.php:
--------------------------------------------------------------------------------
1 |
2 | Details
3 | ===========
4 | Quote: {{var order.quote_id}}
5 | Order: {{var order.increment_id}}
6 | Value: {{var order.base_grand_total}} {{var order.base_currency_code}}
7 | Customer: {{var order.customer_name}} ({{var order.customer_email}})
8 |
9 | Messages
10 | ===========
11 | {{var message}}
12 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/controllers/FraudManager/BlacklistRuleController.php:
--------------------------------------------------------------------------------
1 | getUrl($route, $params);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/modman:
--------------------------------------------------------------------------------
1 | app/etc/modules/Aoe_FraudManager.xml
2 | app/code/local/Aoe/FraudManager
3 | app/design/adminhtml/default/default/layout/Aoe_FraudManager.xml
4 | app/design/adminhtml/default/default/template/aoe_fraudmanager
5 | skin/adminhtml/default/default/css/aoe_fraudmanager.css
6 | #skin/adminhtml/default/default/js/aoe_fraudmanager
7 | #skin/adminhtml/default/default/images/aoe_fraudmanager
8 | app/locale/en_US/Aoe_FraudManager.csv
9 | app/locale/en_US/template/email/aoe_fraudmanager
10 |
--------------------------------------------------------------------------------
/app/etc/modules/Aoe_FraudManager.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | local
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Config/Source/Order/HoldStatusesNone.php:
--------------------------------------------------------------------------------
1 | '', 'label' => Mage::helper('Aoe_FraudManager')->__('-- None --')]);
11 |
12 | return $options;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Form/Element/Renderer/Conditions.php:
--------------------------------------------------------------------------------
1 | getValue();
9 | if ($conditions instanceof Aoe_FraudManager_Model_Rule_Condition_Root) {
10 | return $conditions->getHtml();
11 | }
12 |
13 | return '';
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://www.aoe.com)
2 |
3 | # Aoe_FraudManager Magento Module
4 |
5 | [](https://travis-ci.org/AOEpeople/Aoe_FraudManager)
6 |
7 | ## License
8 | [OSL v3.0](http://opensource.org/licenses/OSL-3.0)
9 |
10 | ## Contributors
11 | * [Lee Saferite](https://github.com/LeeSaferite) (AOE)
12 |
13 | ## Compatability
14 | * Template Rewrites
15 | * app/design/adminhtml/default/default/template/sales/order/view/info.phtml
16 | * Module Dependencies
17 | * Mage_Core
18 | * Mage_Adminhtml
19 | * Mage_Sales
20 | * Aoe_Layout
21 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aoepeople/aoe_fraudmanager",
3 | "description": "Rule based fraud management for Magento",
4 | "authors": [
5 | {
6 | "name": "Lee Saferite",
7 | "email": "lee.saferite@aoe.com"
8 | }
9 | ],
10 | "license": "OSL-3.0",
11 | "type": "magento-module",
12 | "require": {
13 | "php": ">=5.4",
14 | "magento-hackathon/magento-composer-installer": "*",
15 | "aoepeople/aoe_layout": ">=2.1.1"
16 | },
17 | "require-dev": {
18 | "ecomdev/ecomdev_phpunit": "*",
19 | "squizlabs/php_codesniffer": "*",
20 | "phpmd/phpmd": "*"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/locale/en_US/Aoe_FraudManager.csv:
--------------------------------------------------------------------------------
1 | "Marked order as fraud","Marked order as fraud"
2 | "Marked order as NOT fraud","Marked order as NOT fraud"
3 | "Set Fraud Flag","Set Fraud Flag"
4 | "Remove Fraud Flag","Remove Fraud Flag"
5 | "Fraud","Fraud"
6 | "Mark Fraud","Mark Fraud"
7 | "Unmark Fraud","Unmark Fraud"
8 | "Mark Order #%s as Fraud","Mark Order #%s as Fraud"
9 | "Mark Order #%s as NOT Fraud","Mark Order #%s as NOT Fraud"
10 | "AOE Fraud Manager","AOE Fraud Manager"
11 | "Fraud Flag","Fraud Flag"
12 | "Active","Active"
13 | "Require a comment when setting/removing the flag","Require a comment when setting/removing the flag"
14 | "Blacklist Rules","Blacklist Rules"
15 | "Hold Rules","Hold Rules"
16 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/HoldRule/Collection.php:
--------------------------------------------------------------------------------
1 | _init('Aoe_FraudManager/HoldRule');
8 | }
9 |
10 | public function filterValidForOrder(Mage_Sales_Model_Order $order, $includeInactive = false)
11 | {
12 | if (!$includeInactive) {
13 | $this->addFieldToFilter('is_active', '1');
14 | }
15 | $this->addFieldToFilter('website_ids', ['finset' => $order->getStore()->getWebsiteId()]);
16 | $this->addOrder('sort_order', 'DESC');
17 |
18 | return $this;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/sql/Aoe_FraudManager/install-0.1.0.php:
--------------------------------------------------------------------------------
1 | getNode('global/resources/sales_setup/setup');
3 | $setupClass = $setupConfig->getClassName();
4 | $setupClass = ($setupClass ? $setupClass : 'Mage_Sales_Model_Resource_Setup');
5 | $setup = new $setupClass('sales_setup');
6 | /* @var Mage_Sales_Model_Resource_Setup $setup */
7 |
8 | $setup->startSetup();
9 |
10 | $setup->addAttribute(
11 | Mage_Sales_Model_Order::ENTITY,
12 | 'is_fraud',
13 | [
14 | 'type' => Varien_Db_Ddl_Table::TYPE_BOOLEAN,
15 | 'required' => true,
16 | 'comment' => 'Fraud flag',
17 | 'grid' => true,
18 | ]
19 | );
20 |
21 | $setup->endSetup();
22 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/BlacklistRule/Collection.php:
--------------------------------------------------------------------------------
1 | _init('Aoe_FraudManager/BlacklistRule');
8 | }
9 |
10 | public function filterValidForOrder(Mage_Sales_Model_Order $order, $includeInactive = false)
11 | {
12 | if (!$includeInactive) {
13 | $this->addFieldToFilter('is_active', '1');
14 | }
15 | $this->addFieldToFilter('website_ids', ['finset' => $order->getStore()->getWebsiteId()]);
16 | $this->addOrder('sort_order', 'DESC');
17 |
18 | return $this;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: php
3 | php:
4 | - 5.4
5 | - 5.5
6 | env:
7 | matrix:
8 | - MAGENTO_VERSION=magento-mirror-1.9.1.1
9 | - MAGENTO_VERSION=magento-mirror-1.9.1.0
10 | - MAGENTO_VERSION=magento-mirror-1.9.0.1
11 | - MAGENTO_VERSION=magento-mirror-1.8.1.0
12 | branches:
13 | except:
14 | - /^\d+\.\d+\.\d+$/
15 | addons:
16 | hosts:
17 | - magento.local
18 | before_script:
19 | - curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
20 | script:
21 | # Code Style
22 | - php phpcs.phar --standard=./phpcs.xml --encoding=utf-8 --report-width=180 ./app
23 | # Unit Tests
24 | - bash ./run_tests.sh
25 | notifications:
26 | email:
27 | recipients: [ clemens.queissner@aoe.com ]
28 | on_failure: always
29 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/HoldRule.php:
--------------------------------------------------------------------------------
1 | [
7 | '[]',
8 | [],
9 | false,
10 | ['Aoe_FraudManager_Resource_HoldRule', 'implodeArray'],
11 | ['Aoe_FraudManager_Resource_HoldRule', 'explodeArray'],
12 | ],
13 | 'conditions' => [
14 | '[]',
15 | [],
16 | false,
17 | ['Zend_Json', 'encode'],
18 | ['Zend_Json', 'decode'],
19 | ],
20 | ];
21 |
22 | public function _construct()
23 | {
24 | $this->_init('Aoe_FraudManager/HoldRule', 'id');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/BlacklistRule.php:
--------------------------------------------------------------------------------
1 | [
7 | '[]',
8 | [],
9 | false,
10 | ['Aoe_FraudManager_Resource_BlacklistRule', 'implodeArray'],
11 | ['Aoe_FraudManager_Resource_BlacklistRule', 'explodeArray'],
12 | ],
13 | 'conditions' => [
14 | '[]',
15 | [],
16 | false,
17 | ['Zend_Json', 'encode'],
18 | ['Zend_Json', 'decode'],
19 | ],
20 | ];
21 |
22 | public function _construct()
23 | {
24 | $this->_init('Aoe_FraudManager/BlacklistRule', 'id');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/BillingAddress/Attribute.php:
--------------------------------------------------------------------------------
1 | setType('Aoe_FraudManager/Rule_Condition_Order_BillingAddress_Attribute');
9 | $this->setName('Billing Address');
10 | }
11 |
12 | public function validate(Varien_Object $object)
13 | {
14 | /** @var Mage_Sales_Model_Order_Address $object */
15 | if (!$object instanceof Mage_Sales_Model_Order_Address && is_callable([$object, 'getBillingAddress'])) {
16 | $object = $object->getBillingAddress();
17 | }
18 |
19 | return parent::validate($object);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/aoe_fraudmanager/rule/fieldset.phtml:
--------------------------------------------------------------------------------
1 | getElement() ?>
2 |
3 |
4 |
5 |
6 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/ShippingAddress/Attribute.php:
--------------------------------------------------------------------------------
1 | setType('Aoe_FraudManager/Rule_Condition_Order_ShippingAddress_Attribute');
9 | $this->setName('Shipping Address');
10 | }
11 |
12 | public function validate(Varien_Object $object)
13 | {
14 | /** @var Mage_Sales_Model_Order_Address $object */
15 | if (!$object instanceof Mage_Sales_Model_Order_Address && is_callable([$object, 'getShippingAddress'])) {
16 | $object = $object->getShippingAddress();
17 | }
18 |
19 | return parent::validate($object);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Root.php:
--------------------------------------------------------------------------------
1 | setParentType($this->getType());
13 |
14 | $this->setId('root');
15 | $this->setType('Aoe_FraudManager/Rule_Condition_Root');
16 | }
17 |
18 | public function getSelfType()
19 | {
20 | return $this->getParentType();
21 | }
22 |
23 | //==================================================
24 | //=[ HTML Generation ]==============================
25 | //==================================================
26 |
27 | public function getRemoveLinkHtml()
28 | {
29 | return '';
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Form/Element/Renderer/Newchild.php:
--------------------------------------------------------------------------------
1 | addClass('element-value-changer');
8 |
9 | $html = ' ';
10 |
11 | $html .= '';
12 | $src = Mage::getDesign()->getSkinUrl('images/rule_component_add.gif');
13 | $html .= '
';
14 | $html .= '';
15 |
16 | $html .= '';
17 | $html .= $element->getElementHtml();
18 | $html .= '';
19 |
20 | $html .= ' ';
21 |
22 | return $html;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Item/Combine.php:
--------------------------------------------------------------------------------
1 | setType('Aoe_FraudManager/Rule_Condition_Order_Item_Combine');
12 | $this->setName('Conditions Combination');
13 | }
14 |
15 | /**
16 | * Get conditions selectors
17 | *
18 | * @return array
19 | */
20 | public function getNewChildOptions()
21 | {
22 | $conditions = ['' => $this->translate('Please choose a condition to add...')];
23 |
24 | // Fire an event to add conditions
25 | $container = new Varien_Object();
26 | Mage::dispatchEvent('aoe_fraudmanager_rule_condition_order_item_combine_conditions', ['parent' => $this, 'container' => $container]);
27 | if ($additional = $container->getConditions()) {
28 | $conditions = array_merge($conditions, $additional);
29 | }
30 |
31 | return $conditions;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Form/Element/Select.php:
--------------------------------------------------------------------------------
1 | getValues();
8 | if (empty($values)) {
9 | $options = $this->getOptions();
10 | if (is_array($options)) {
11 | $values = $this->convertOptionsToValues($options);
12 | } elseif (is_string($options)) {
13 | $values = [['value' => $options, 'label' => $options]];
14 | }
15 | $this->setValues($values);
16 | }
17 | }
18 |
19 | protected function convertOptionsToValues(array $options)
20 | {
21 | $values = [];
22 |
23 | foreach ($options as $value => $label) {
24 | if (is_array($label)) {
25 | $values[] = [
26 | 'label' => $value,
27 | 'value' => $this->convertOptionsToValues($label),
28 | ];
29 | } else {
30 | $values[] = [
31 | 'label' => $label,
32 | 'value' => $value,
33 | ];
34 | }
35 | }
36 |
37 | return $values;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Magento extension ruleset based on PSR-2 but modified for Magento 1
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Interface.php:
--------------------------------------------------------------------------------
1 |
27 |
28 | getFormHtml() ?>
29 |
30 |
38 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Item/Attribute.php:
--------------------------------------------------------------------------------
1 | ['SKU', ['==', '!=', '{}', '!{}', 'RE']],
7 | 'qty_ordered' => ['Qty', ['==', '!=', '<', '<=', '>', '>=']],
8 | 'weight' => ['Weight', ['==', '!=', '<', '<=', '>', '>=']],
9 | 'row_weight' => ['Row Weight', ['==', '!=', '<', '<=', '>', '>=']],
10 | 'price' => ['Price', ['==', '!=', '<', '<=', '>', '>=']],
11 | 'original_price' => ['Original Price', ['==', '!=', '<', '<=', '>', '>=']],
12 | 'tax_percent' => ['Tax Percent', ['==', '!=', '<', '<=', '>', '>=']],
13 | 'tax_amount' => ['Tax Amount', ['==', '!=', '<', '<=', '>', '>=']],
14 | 'discount_percent' => ['Discount Percent', ['==', '!=', '<', '<=', '>', '>=']],
15 | 'discount_amount' => ['Discount Amount', ['==', '!=', '<', '<=', '>', '>=']],
16 | 'row_total' => ['Row Total', ['==', '!=', '<', '<=', '>', '>=']],
17 | 'row_total_incl_tax' => ['Row Total w/Tax', ['==', '!=', '<', '<=', '>', '>=']],
18 | ];
19 |
20 | protected function _construct()
21 | {
22 | parent::_construct();
23 | $this->setType('Aoe_FraudManager/Rule_Condition_Order_Item_Attribute');
24 | $this->setName('Order Item');
25 | }
26 |
27 | public function validate(Varien_Object $object)
28 | {
29 | /** @var Mage_Sales_Model_Order_Item $object */
30 | if (!$object instanceof Mage_Sales_Model_Order_Item) {
31 | return false;
32 | }
33 |
34 | return parent::validate($object);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Test/Model/HoldRule.php:
--------------------------------------------------------------------------------
1 |
5 | * @since 2015-08-06
6 | */
7 | class Aoe_FraudManager_Test_Model_HoldRule extends EcomDev_PHPUnit_Test_Case
8 | {
9 | /**
10 | * @test
11 | */
12 | public function getModel()
13 | {
14 | /** @var Aoe_FraudManager_Model_HoldRule $model */
15 | $model = Mage::getModel('Aoe_FraudManager/HoldRule');
16 | $this->assertInstanceOf('Aoe_FraudManager_Model_HoldRule', $model);
17 |
18 | return $model;
19 | }
20 |
21 | /**
22 | * @test
23 | *
24 | * @depends getModel
25 | *
26 | * @param Aoe_FraudManager_Model_HoldRule $model
27 | */
28 | public function getModelResource(Aoe_FraudManager_Model_HoldRule $model)
29 | {
30 | /** @var Aoe_FraudManager_Resource_HoldRule $resource */
31 | $resource = $model->getResource();
32 | $this->assertInstanceOf('Aoe_FraudManager_Resource_HoldRule', $resource);
33 |
34 | /** @var Aoe_FraudManager_Resource_HoldRule $resource */
35 | $resource = Mage::getResourceModel('Aoe_FraudManager/HoldRule');
36 | $this->assertInstanceOf('Aoe_FraudManager_Resource_HoldRule', $resource);
37 | }
38 |
39 | /**
40 | * @test
41 | *
42 | * @depends getModel
43 | *
44 | * @param Aoe_FraudManager_Model_HoldRule $model
45 | */
46 | public function getModelCollection(Aoe_FraudManager_Model_HoldRule $model)
47 | {
48 | /** @var Aoe_FraudManager_Resource_HoldRule_Collection $collection */
49 | $collection = $model->getResourceCollection();
50 | $this->assertInstanceOf('Aoe_FraudManager_Resource_HoldRule_Collection', $collection);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Test/Model/BlacklistRule.php:
--------------------------------------------------------------------------------
1 |
5 | * @since 2015-08-06
6 | */
7 | class Aoe_FraudManager_Test_Model_BlacklistRule extends EcomDev_PHPUnit_Test_Case
8 | {
9 | /**
10 | * @test
11 | */
12 | public function getModel()
13 | {
14 | /** @var Aoe_FraudManager_Model_BlacklistRule $model */
15 | $model = Mage::getModel('Aoe_FraudManager/BlacklistRule');
16 | $this->assertInstanceOf('Aoe_FraudManager_Model_BlacklistRule', $model);
17 |
18 | return $model;
19 | }
20 |
21 | /**
22 | * @test
23 | *
24 | * @depends getModel
25 | *
26 | * @param Aoe_FraudManager_Model_BlacklistRule $model
27 | */
28 | public function getModelResource(Aoe_FraudManager_Model_BlacklistRule $model)
29 | {
30 | /** @var Aoe_FraudManager_Resource_BlacklistRule $resource */
31 | $resource = $model->getResource();
32 | $this->assertInstanceOf('Aoe_FraudManager_Resource_BlacklistRule', $resource);
33 |
34 | /** @var Aoe_FraudManager_Resource_BlacklistRule $resource */
35 | $resource = Mage::getResourceModel('Aoe_FraudManager/BlacklistRule');
36 | $this->assertInstanceOf('Aoe_FraudManager_Resource_BlacklistRule', $resource);
37 | }
38 |
39 | /**
40 | * @test
41 | *
42 | * @depends getModel
43 | *
44 | * @param Aoe_FraudManager_Model_BlacklistRule $model
45 | */
46 | public function getModelCollection(Aoe_FraudManager_Model_BlacklistRule $model)
47 | {
48 | /** @var Aoe_FraudManager_Resource_BlacklistRule_Collection $collection */
49 | $collection = $model->getResourceCollection();
50 | $this->assertInstanceOf('Aoe_FraudManager_Resource_BlacklistRule_Collection', $collection);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/aoe_fraudmanager/rule/js.phtml:
--------------------------------------------------------------------------------
1 |
27 |
46 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Address/Attribute.php:
--------------------------------------------------------------------------------
1 | ['Full Name', ['==', '!=', '{}', '!{}', 'RE']],
7 | 'firstname' => ['First Name', ['==', '!=', '{}', '!{}', 'RE']],
8 | 'lastname' => ['Last Name', ['==', '!=', '{}', '!{}', 'RE']],
9 | 'street_full' => ['Street', ['==', '!=', '{}', '!{}', 'RE']],
10 | 'city' => ['City', ['==', '!=', '{}', '!{}', 'RE']],
11 | 'region' => ['Region', ['==', '!=', '{}', '!{}', 'RE']],
12 | 'country_id' => ['Country', ['==', '!=', 'RE']],
13 | 'all' => ['All', ['==', '!=', '{}', '!{}', 'RE']],
14 | ];
15 |
16 | protected function getAttributeValue(Varien_Object $object)
17 | {
18 | $attribute = $this->getAttribute();
19 | if (empty($attribute)) {
20 | return null;
21 | }
22 |
23 | /** @var Mage_Sales_Model_Order_Address $object */
24 | if ($object instanceof Mage_Sales_Model_Order_Address && $attribute === 'all') {
25 | $value = $object->format("text");
26 | } else {
27 | $value = $object->getDataUsingMethod($attribute);
28 | }
29 |
30 | if (is_scalar($value)) {
31 | // Convert 2+ spaces in a row into a single space
32 | $value = preg_replace('/ {2,}/u', ' ', $value);
33 |
34 | // Remove leading/trailing spaces
35 | $value = trim($value);
36 | }
37 |
38 | return $value;
39 | }
40 |
41 | public function validate(Varien_Object $object)
42 | {
43 | /** @var Mage_Sales_Model_Order_Address $object */
44 | if (!$object instanceof Mage_Sales_Model_Order_Address) {
45 | return false;
46 | }
47 |
48 | return parent::validate($object);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Form/Element/Renderer/Editable.php:
--------------------------------------------------------------------------------
1 | addClass('element-value-changer');
8 | $valueName = $element->getLabel();
9 |
10 | if ($valueName === '' || $valueName === null) {
11 | $valueName = '...';
12 | }
13 |
14 | if ($element->getShowAsText()) {
15 | $html = ' '
17 | . htmlspecialchars($valueName) . ' ';
18 | } else {
19 | $html = ' ';
20 |
21 | /** @var Mage_Core_Model_Translate_Inline $translate */
22 | $translate = Mage::getSingleton('core/translate_inline');
23 | if ($translate->isAllowed()) {
24 | $valueName = Mage::helper('core/string')->truncate($valueName, 33, '...');
25 | }
26 |
27 | $html .= '';
28 | $html .= Mage::helper('core')->escapeHtml($valueName);
29 | $html .= '';
30 |
31 | $html .= ' ';
32 | $html .= $element->getElementHtml();
33 | if ($element->getExplicitApply()) {
34 | /** @var Aoe_FraudManager_Helper_Data $helper */
35 | $helper = Mage::helper('Aoe_FraudManager/Data');
36 | $url = $helper->getConditionApplyImageUrl();
37 | $label = $helper->getConditionApplyLabel();
38 |
39 | $html .= ' ';
40 | $html .= '
';
41 | $html .= ' ';
42 | }
43 | $html .= '';
44 |
45 | $html .= ' ';
46 | }
47 |
48 | return $html;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Attribute.php:
--------------------------------------------------------------------------------
1 | ['Grand Total', ['==', '!=', '<=', '<', '>=', '>']],
7 | 'customer_email' => ['Email Address', ['==', '!=', '{}', '!{}', 'RE']],
8 | 'email_domain' => ['Email Domain', ['()', '!()', 'RE']],
9 | 'remote_ip' => ['Remote IP', ['()', '!()']],
10 | 'shipping_method' => ['Shipping Method', ['{}', '!{}', '()', '!()', 'RE']],
11 | ];
12 |
13 | protected $attributeOptions = null;
14 |
15 | /**
16 | * Internal constructor not depended on params. Can be used for object initialization
17 | */
18 | protected function _construct()
19 | {
20 | parent::_construct();
21 | $this->setType('Aoe_FraudManager/Rule_Condition_Order_Attribute');
22 | $this->setName('Order');
23 | }
24 |
25 | public function validate(Varien_Object $object)
26 | {
27 | if (!$object instanceof Mage_Sales_Model_Order) {
28 | if (is_callable([$object, 'getOrder'])) {
29 | $object = $object->getOrder();
30 | if (!$object instanceof Mage_Sales_Model_Order) {
31 | return false;
32 | }
33 | } else {
34 | return false;
35 | }
36 | }
37 |
38 | return parent::validate($object);
39 | }
40 |
41 | protected function getAttributeValue(Varien_Object $object)
42 | {
43 | switch ($this->getAttribute()) {
44 | case 'email_domain':
45 | $emailAddress = $object->getDataUsingMethod('customer_email');
46 | $emailDomain = substr($emailAddress, strpos($emailAddress, '@') + 1);
47 | $emailDomain = trim(strtolower($emailDomain));
48 |
49 | return $emailDomain;
50 | break;
51 | case 'remote_ip':
52 | $ipList = explode(',', $object->getDataUsingMethod('x_forwarded_for'));
53 | $ipList[] = $object->getDataUsingMethod('remote_ip');
54 | $ipList = array_unique(array_filter(array_map('trim', $ipList)));
55 |
56 | return $ipList;
57 | break;
58 | default:
59 | return parent::getAttributeValue($object);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Item/Found.php:
--------------------------------------------------------------------------------
1 | setType('Aoe_FraudManager/Rule_Condition_Order_Item_Found');
13 | $this->setName('Product Attribute Combination');
14 | }
15 |
16 |
17 | /**
18 | * Load value options
19 | *
20 | * @return $this
21 | */
22 | public function getValueOptions()
23 | {
24 | return [
25 | 1 => Mage::helper('salesrule')->__('FOUND'),
26 | 0 => Mage::helper('salesrule')->__('NOT FOUND'),
27 | ];
28 | }
29 |
30 | public function getConditionConfigHtml()
31 | {
32 | $html = $this->translate(
33 | 'If an item is %s in the order with %s of these conditions true:',
34 | $this->getValueElement()->getHtml(),
35 | $this->getAggregatorElement()->getHtml()
36 | );
37 |
38 | return $html;
39 | }
40 |
41 | /**
42 | * @param Varien_Object $object
43 | *
44 | * @return bool
45 | */
46 | public function validate(Varien_Object $object)
47 | {
48 | /** @var Mage_Sales_Model_Order $object */
49 | if (!$object instanceof Mage_Sales_Model_Order) {
50 | return false;
51 | }
52 |
53 | $conditions = $this->getConditions();
54 | if (empty($conditions)) {
55 | return true;
56 | }
57 |
58 | $all = ($this->getAggregator() === 'all');
59 | $true = (bool)$this->getValue();
60 |
61 | $found = false;
62 | foreach ($object->getAllItems() as $item) {
63 | /** @var Mage_Sales_Model_Order_Item $item */
64 | $found = $all;
65 | foreach ($conditions as $cond) {
66 | $validated = $cond->validate($item);
67 | if ($all !== $validated) {
68 | $found = $validated;
69 | break;
70 | }
71 | }
72 |
73 | if ($found) {
74 | break;
75 | }
76 | }
77 |
78 | // found an item and we're looking for existing one
79 | if ($found && $true) {
80 | return true;
81 | } // not found and we're making sure it doesn't exist
82 | elseif (!$found && !$true) {
83 | return true;
84 | }
85 |
86 | return false;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # check if this is a travis environment
5 | if [ -n "${TRAVIS_BUILD_DIR}" ] ; then
6 | WORKSPACE=${TRAVIS_BUILD_DIR}
7 | fi
8 |
9 | if [ -z "${WORKSPACE}" ] ; then
10 | echo "No workspace configured, please set your WORKSPACE environment"
11 | exit
12 | fi
13 |
14 | # Create a working directory that is removed on exit
15 | function cleanup {
16 | if [ -z "${SKIP_CLEANUP}" -a -n "${BUILDENV}" ]; then
17 | echo "Removing build directory ${BUILDENV}"
18 | rm -rf "${BUILDENV}"
19 | fi
20 | }
21 | trap cleanup EXIT
22 | BUILDENV=`mktemp -d /tmp/buildenv.XXXXXXXX`
23 | echo "Using build directory ${BUILDENV}"
24 |
25 | # Grab the composer package name for the package we are testing
26 | COMPOSER_PACKAGE_NAME=`jq -r '.name' "${WORKSPACE}/composer.json"`
27 |
28 | # Initialize git
29 | echo "Setting git user information"
30 | if [ -z "`git config --get user.name`" ] ; then
31 | git config --global user.name "CI System"
32 | fi
33 | if [ -z "`git config --get user.email`" ] ; then
34 | git config --global user.email "ci@aoe.com"
35 | fi
36 |
37 | # Add a fake version into the composer.json of the package we are testing
38 | jq '. |= .+ {version:"dev-current"}' "${WORKSPACE}/composer.json" > "${WORKSPACE}/composer.json.new"
39 | mv -f "${WORKSPACE}/composer.json.new" "${WORKSPACE}/composer.json"
40 |
41 | # Create artifact with update composer.json
42 | ARTIFACT_NAME=`echo ${COMPOSER_PACKAGE_NAME} | tr / -`
43 | git stash
44 | cd "${WORKSPACE}"
45 | mkdir "${BUILDENV}/artifacts"
46 | git archive -o "${BUILDENV}/artifacts/${ARTIFACT_NAME}.zip" stash@{0}
47 | git stash drop
48 |
49 | # Checkout the testing framework
50 | TESTSTAND="${BUILDENV}/teststand"
51 | mkdir "${TESTSTAND}"
52 | echo "Cloning AOEpeople/MageTestStand into ${TESTSTAND}"
53 | git clone https://github.com/AOEpeople/MageTestStand.git "${TESTSTAND}"
54 |
55 | # Add testing framework to PATH
56 | PATH="${TESTSTAND}/tools:${TESTSTAND}/bin:${PATH}"
57 |
58 | # Update n98-magerun
59 | n98-magerun.phar self-update
60 |
61 | # Update composer
62 | composer.phar self-update
63 |
64 | # Add the artifact repository to the testing framework
65 | echo "Add the artifact repository to the testing framework"
66 | jq ".repositories |= .+ [{type:\"artifact\", url:\"${BUILDENV}/artifacts\"}]" "${TESTSTAND}/composer.json" > "${TESTSTAND}/composer.json.new"
67 | mv -f "${TESTSTAND}/composer.json.new" "${TESTSTAND}/composer.json"
68 |
69 | # Use composer to require the package being tested
70 | cd "${TESTSTAND}"
71 | composer.phar require --no-interaction --no-progress ${COMPOSER_PACKAGE_NAME}:dev-current
72 |
73 | # Use modman to deploy any Magento modules
74 | cd "${TESTSTAND}"
75 | echo "Installing Magento Test Framework"
76 | bash ./install.sh
77 |
78 | # Run PHPUnit
79 | cd "${TESTSTAND}/htdocs"
80 | phpunit --colors -d display_errors=1
81 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Order/Address/Compare.php:
--------------------------------------------------------------------------------
1 | ['Full Name', ['==', '!=']],
7 | 'firstname' => ['First Name', ['==', '!=']],
8 | 'lastname' => ['Last Name', ['==', '!=']],
9 | 'street_full' => ['Street', ['==', '!=']],
10 | 'city' => ['City', ['==', '!=']],
11 | 'region' => ['Region', ['==', '!=']],
12 | 'country_id' => ['Country', ['==', '!=']],
13 | 'all' => ['All', ['==', '!=']],
14 | ];
15 |
16 | protected function _construct()
17 | {
18 | parent::_construct();
19 | $this->setType('Aoe_FraudManager/Rule_Condition_Order_Address_Compare');
20 | $this->setName('Compare Billing and Shipping Addresses');
21 | }
22 |
23 | public function validate(Varien_Object $object)
24 | {
25 | if ($object instanceof Mage_Sales_Model_Order) {
26 | $order = $object;
27 | } elseif ($object instanceof Mage_Sales_Model_Order_Address) {
28 | $order = $object->getOrder();
29 | } else {
30 | // Cannot test
31 | return false;
32 | }
33 |
34 | /** @var Mage_Sales_Model_Order_Address $object */
35 | $billingAddress = $order->getBillingAddress();
36 | $shippingAddress = $order->getShippingAddress();
37 |
38 | if (!$billingAddress || !$shippingAddress) {
39 | // Cannot test
40 | return false;
41 | }
42 |
43 | $attribute = $this->getAttribute();
44 | if (empty($attribute)) {
45 | // Cannot test
46 | return false;
47 | }
48 |
49 | return Mage::helper('Aoe_FraudManager/Condition')->validateValue($this->getOperator(), $this->getAttributeValue($billingAddress), $this->getAttributeValue($shippingAddress));
50 | }
51 |
52 | /**
53 | * @return array
54 | */
55 | public function getOperatorOptions()
56 | {
57 | $allowedOperators = parent::getOperatorOptions();
58 |
59 | if (isset($allowedOperators['=='])) {
60 | $allowedOperators['=='] = Mage::helper('Aoe_FraudManager')->__('is the same');
61 | }
62 |
63 | if (isset($allowedOperators['!='])) {
64 | $allowedOperators['!='] = Mage::helper('Aoe_FraudManager')->__('is not the same');
65 | }
66 |
67 | return $allowedOperators;
68 | }
69 |
70 | public function getConditionConfigHtml()
71 | {
72 | $html = $this->translate('Billing and Shipping') . ' ';
73 | $html .= $this->getAttributeElement()->getHtml();
74 | $html .= $this->getOperatorElement()->getHtml();
75 | $html .= $this->getChooserContainerHtml();
76 |
77 | return $html;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Controller/RuleController.php:
--------------------------------------------------------------------------------
1 | getRequest()->getParam('order', $this->getRequest()->getParam('order_id'));
8 |
9 | /** @var Mage_Sales_Model_Order $order */
10 | $order = Mage::getModel('sales/order')->load($id);
11 | if ($order->isObjectNew()) {
12 | $e = new Mage_Core_Controller_Varien_Exception();
13 | throw $e->prepareForward('noroute');
14 | }
15 |
16 | /** @var Aoe_FraudManager_Helper_AbstractRule $helper */
17 | $helper = $this->getHelper();
18 | $helper->setCurrentOrder($order);
19 |
20 | $this->loadLayout();
21 | $this->renderLayout();
22 | }
23 |
24 | public function conditionAction()
25 | {
26 | if (!$this->getRequest()->isAjax()) {
27 | $this->_forward('noroute');
28 |
29 | return;
30 | }
31 |
32 | $id = $this->getRequest()->getParam('id');
33 | $type = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
34 |
35 | /** @var Aoe_FraudManager_Model_Rule_Condition_Interface $condition */
36 | $condition = Mage::getModel($type[0]);
37 | if (!$condition instanceof Aoe_FraudManager_Model_Rule_Condition_Interface) {
38 | $this->_forward('noroute');
39 |
40 | return;
41 | }
42 |
43 | /** @var Aoe_FraudManager_Model_Rule_Abstract $rule */
44 | $rule = $this->getHelper()->getModel();
45 |
46 | $condition->setId($id);
47 | $condition->setRule($rule);
48 | if (is_callable([$condition, 'setJsFormObject'])) {
49 | $condition->setJsFormObject($this->getRequest()->getParam('form'));
50 | }
51 | if (isset($type[1]) && is_callable([$condition, 'setAttribute'])) {
52 | $condition->setAttribute($type[1]);
53 | }
54 |
55 | $this->getResponse()->setBody($condition->getHtml());
56 | }
57 |
58 | /**
59 | * Pre-process the POST data before adding to the model
60 | *
61 | * @param array $postData
62 | *
63 | * @return array
64 | */
65 | protected function preprocessPostData(array $postData)
66 | {
67 | $postData = parent::preprocessPostData($postData);
68 |
69 | if (isset($postData['rule']) && is_array($postData['rule'])) {
70 | $rule = $this->getHelper()->convertFlatToRecursive($postData['rule'], ['conditions']);
71 | unset($postData['rule']);
72 | if (isset($rule['conditions'])) {
73 | $postData['conditions'] = reset($rule['conditions']);
74 | }
75 | }
76 |
77 | return $postData;
78 | }
79 |
80 | protected function getAclActionName()
81 | {
82 | $action = Aoe_Layout_Controller_Model::getAclActionName();
83 |
84 | if ($action === 'testOrder') {
85 | $action = 'test';
86 | } elseif ($action !== 'view') {
87 | $action = 'edit';
88 | }
89 |
90 | return $action;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Abstract.php:
--------------------------------------------------------------------------------
1 | getData('conditions');
27 | if (!$conditions instanceof Aoe_FraudManager_Model_Rule_Condition_Root) {
28 | if (is_array($conditions) && isset($conditions['type'])) {
29 | $root = Mage::getModel($conditions['type']);
30 | if (!$root instanceof Aoe_FraudManager_Model_Rule_Condition_Root) {
31 | Mage::throwException('Invalid parameter');
32 | }
33 | $root->setRule($this);
34 | $root->loadArray($conditions);
35 | } else {
36 | $root = Mage::getModel('Aoe_FraudManager/Rule_Condition_Root');
37 | $root->setRule($this);
38 | }
39 |
40 | $this->setData('conditions', $root);
41 | $conditions = $root;
42 | }
43 |
44 | return $conditions;
45 | }
46 |
47 | /**
48 | * Set rule combine conditions model
49 | *
50 | * @param Aoe_FraudManager_Model_Rule_Condition_Root|array $conditions
51 | *
52 | * @return $this
53 | */
54 | public function setConditions($conditions)
55 | {
56 | if ($conditions instanceof Aoe_FraudManager_Model_Rule_Condition_Root) {
57 | $this->root = $conditions;
58 | $this->setData('conditions', $this->root);
59 | } elseif (is_array($conditions)) {
60 | $this->setData('conditions', $conditions);
61 | $this->getConditions();
62 | } else {
63 | Mage::throwException('Invalid parameter');
64 | }
65 |
66 | return $this;
67 | }
68 |
69 | /**
70 | * Rule form getter
71 | *
72 | * @return Varien_Data_Form
73 | */
74 | public function getConditionsForm()
75 | {
76 | if (!$this->conditionsForm) {
77 | $this->conditionsForm = new Varien_Data_Form();
78 | $this->conditionsForm->setHtmlIdPrefix('rule__conditions__');
79 | $this->conditionsForm->setFieldNameSuffix('rule[conditions]');
80 | $this->conditionsForm->addType('select', Mage::getConfig()->getModelClassName('Aoe_FraudManager/Form_Element_Select'));
81 | }
82 |
83 | return $this->conditionsForm;
84 | }
85 |
86 | /**
87 | * Validate rule conditions to determine if rule can run
88 | *
89 | * @param Varien_Object $object
90 | *
91 | * @return bool
92 | */
93 | public function validate(Varien_Object $object)
94 | {
95 | return $this->getConditions()->validate($object);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/sql/Aoe_FraudManager/upgrade-0.1.0-0.2.0.php:
--------------------------------------------------------------------------------
1 | startSetup();
4 |
5 | $this->getConnection()->dropTable($this->getTable('Aoe_FraudManager/BlacklistRule'));
6 | $this->getConnection()->dropTable($this->getTable('Aoe_FraudManager/HoldRule'));
7 |
8 | $table = $this->getConnection()->newTable($this->getTable('Aoe_FraudManager/BlacklistRule'));
9 | $table->addColumn(
10 | 'id',
11 | Varien_Db_Ddl_Table::TYPE_INTEGER,
12 | null,
13 | [
14 | 'primary' => true,
15 | 'identity' => true,
16 | 'unsigned' => true,
17 | 'nullable' => false,
18 | ]
19 | );
20 | $table->addColumn(
21 | 'name',
22 | Varien_Db_Ddl_Table::TYPE_TEXT,
23 | pow(2, 8) - 1,
24 | ['nullable' => false]
25 | );
26 | $table->addColumn(
27 | 'description',
28 | Varien_Db_Ddl_Table::TYPE_TEXT,
29 | pow(2, 16) - 1
30 | );
31 | $table->addColumn(
32 | 'message',
33 | Varien_Db_Ddl_Table::TYPE_TEXT,
34 | pow(2, 16) - 1
35 | );
36 | $table->addColumn(
37 | 'stop_processing',
38 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
39 | null,
40 | ['nullable' => false]
41 | );
42 | $table->addColumn(
43 | 'is_active',
44 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
45 | null,
46 | ['nullable' => false]
47 | );
48 | $table->addColumn(
49 | 'conditions',
50 | Varien_Db_Ddl_Table::TYPE_TEXT,
51 | pow(2, 32) - 1
52 | );
53 | $table->addColumn(
54 | 'website_ids',
55 | Varien_Db_Ddl_Table::TYPE_TEXT,
56 | pow(2, 16) - 1
57 | );
58 | $table->addColumn(
59 | 'sort_order',
60 | Varien_Db_Ddl_Table::TYPE_INTEGER,
61 | null,
62 | ['nullable' => false]
63 | );
64 | $table->addIndex(
65 | $this->getIdxName('Aoe_FraudManager/BlacklistRule', ['is_active']),
66 | ['is_active']
67 | );
68 | $this->getConnection()->createTable($table);
69 |
70 | $table = $this->getConnection()->newTable($this->getTable('Aoe_FraudManager/HoldRule'));
71 | $table->addColumn(
72 | 'id',
73 | Varien_Db_Ddl_Table::TYPE_INTEGER,
74 | null,
75 | [
76 | 'primary' => true,
77 | 'identity' => true,
78 | 'unsigned' => true,
79 | 'nullable' => false,
80 | ]
81 | );
82 | $table->addColumn(
83 | 'name',
84 | Varien_Db_Ddl_Table::TYPE_TEXT,
85 | pow(2, 8) - 1,
86 | ['nullable' => false]
87 | );
88 | $table->addColumn(
89 | 'description',
90 | Varien_Db_Ddl_Table::TYPE_TEXT,
91 | pow(2, 16) - 1
92 | );
93 | $table->addColumn(
94 | 'status',
95 | Varien_Db_Ddl_Table::TYPE_TEXT,
96 | 32,
97 | ['nullable' => true]
98 | );
99 | $table->addColumn(
100 | 'stop_processing',
101 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
102 | null,
103 | ['nullable' => false]
104 | );
105 | $table->addColumn(
106 | 'is_active',
107 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
108 | null,
109 | ['nullable' => false]
110 | );
111 | $table->addColumn(
112 | 'conditions',
113 | Varien_Db_Ddl_Table::TYPE_TEXT,
114 | pow(2, 32) - 1
115 | );
116 | $table->addColumn(
117 | 'website_ids',
118 | Varien_Db_Ddl_Table::TYPE_TEXT,
119 | pow(2, 16) - 1
120 | );
121 | $table->addColumn(
122 | 'sort_order',
123 | Varien_Db_Ddl_Table::TYPE_INTEGER,
124 | null,
125 | ['nullable' => false]
126 | );
127 | $table->addIndex(
128 | $this->getIdxName('Aoe_FraudManager/HoldRule', ['is_active']),
129 | ['is_active']
130 | );
131 | $this->getConnection()->createTable($table);
132 |
133 | $this->endSetup();
134 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/controllers/Sales/OrderController.php:
--------------------------------------------------------------------------------
1 | getHelper();
11 | $order = $this->initOrder();
12 | try {
13 | if ($this->getRequest()->isPost() || !$helper->isSetFlagCommentRequired($order)) {
14 | $comment = trim($this->getRequest()->getPost('comment'));
15 | if ($helper->setFlag($order, $comment)) {
16 | $this->_getSession()->addSuccess($this->__('Marked order as fraud'));
17 | }
18 | $this->redirectToOrderView($order);
19 | } else {
20 | $this->loadLayout();
21 | $this->_setActiveMenu('sales/order');
22 | $this->_addBreadcrumb($this->__('Sales'), $this->__('Sales'));
23 | $this->_addBreadcrumb($this->__('Orders'), $this->__('Orders'));
24 | $this->renderLayout();
25 | }
26 | } catch (Exception $e) {
27 | Mage::logException($e);
28 | $this->_getSession()->addError($e->getMessage());
29 | $this->redirectToOrderView($order);
30 | }
31 | }
32 |
33 | public function removeFraudFlagAction()
34 | {
35 | $helper = $this->getHelper();
36 | $order = $this->initOrder();
37 | try {
38 | if ($this->getRequest()->isPost() || !$helper->isRemoveFlagCommentRequired($order)) {
39 | $comment = trim($this->getRequest()->getPost('comment'));
40 | if ($helper->removeFlag($order, $comment)) {
41 | $this->_getSession()->addSuccess($this->__('Marked order as NOT fraud'));
42 | }
43 | $this->redirectToOrderView($order);
44 | } else {
45 | $this->loadLayout();
46 | $this->_setActiveMenu('sales/order');
47 | $this->_addBreadcrumb($this->__('Sales'), $this->__('Sales'));
48 | $this->_addBreadcrumb($this->__('Orders'), $this->__('Orders'));
49 | $this->renderLayout();
50 | }
51 | } catch (Exception $e) {
52 | Mage::logException($e);
53 | $this->_getSession()->addError($e->getMessage());
54 | $this->redirectToOrderView($order);
55 | }
56 | }
57 |
58 | /**
59 | * @return Mage_Sales_Model_Order
60 | *
61 | * @throws Mage_Core_Controller_Varien_Exception
62 | */
63 | protected function initOrder()
64 | {
65 | $id = $this->getRequest()->getParam('order', $this->getRequest()->getParam('order_id'));
66 |
67 | /** @var Mage_Sales_Model_Order $order */
68 | $order = Mage::getModel('sales/order')->load($id);
69 | if ($order->isObjectNew()) {
70 | $e = new Mage_Core_Controller_Varien_Exception();
71 | throw $e->prepareForward('noroute');
72 | }
73 |
74 | $this->getHelper()->setCurrentOrder($order);
75 |
76 | return $order;
77 | }
78 |
79 | /**
80 | * Issue a redirect to the order view page
81 | *
82 | * @param Mage_Sales_Model_Order $order
83 | *
84 | * @return $this
85 | */
86 | protected function redirectToOrderView(Mage_Sales_Model_Order $order)
87 | {
88 | return $this->_redirect('adminhtml/sales_order/view', ['order_id' => $order->getId()]);
89 | }
90 |
91 | /**
92 | * @return Aoe_FraudManager_Helper_FraudFlag
93 | */
94 | protected function getHelper()
95 | {
96 | return Mage::helper('Aoe_FraudManager/FraudFlag');
97 | }
98 |
99 | /**
100 | * ACL check
101 | *
102 | * @return bool
103 | */
104 | protected function _isAllowed()
105 | {
106 | $order = $this->initOrder();
107 | $allowed = false;
108 |
109 | $action = lcfirst($this->getRequest()->getActionName());
110 | switch ($action) {
111 | case 'setFraudFlag':
112 | $allowed = $this->getHelper()->isSetFlagActionAllowed($order);
113 | break;
114 | case 'removeFraudFlag':
115 | $allowed = $this->getHelper()->isRemoveFlagActionAllowed($order);
116 | break;
117 | }
118 |
119 | return $allowed;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Abstract.php:
--------------------------------------------------------------------------------
1 | getData('type');
24 | }
25 |
26 | public function getName()
27 | {
28 | return $this->getData('name');
29 | }
30 |
31 | /**
32 | * @return Aoe_FraudManager_Model_Rule_Abstract
33 | */
34 | public function getRule()
35 | {
36 | return parent::getRule();
37 | }
38 |
39 | /**
40 | * @param Aoe_FraudManager_Model_Rule_Abstract $rule
41 | *
42 | * @return $this
43 | */
44 | public function setRule(Aoe_FraudManager_Model_Rule_Abstract $rule)
45 | {
46 | return parent::setRule($rule);
47 | }
48 |
49 | /**
50 | * @return Varien_Data_Form
51 | */
52 | public function getForm()
53 | {
54 | return $this->getRule()->getConditionsForm();
55 | }
56 |
57 | /**
58 | * @param Varien_Object $object
59 | *
60 | * @return bool
61 | */
62 | abstract public function validate(Varien_Object $object);
63 |
64 | //==================================================
65 | //=[ HTML Generation ]==============================
66 | //==================================================
67 |
68 | public function getHtml()
69 | {
70 | $html = $this->getTypeElement()->getHtml();
71 | $html .= $this->getConditionConfigHtml();
72 | $html .= $this->getRemoveLinkHtml();
73 |
74 | return $html;
75 | }
76 |
77 | public function getTypeElement()
78 | {
79 | $element = $this->getForm()->addField(
80 | $this->getId() . '__type',
81 | 'hidden',
82 | [
83 | 'name' => $this->getId() . '[type]',
84 | 'value' => $this->getType(),
85 | 'no_span' => true,
86 | 'class' => 'hidden',
87 | ]
88 | );
89 |
90 | return $element;
91 | }
92 |
93 | abstract public function getConditionConfigHtml();
94 |
95 | public function getRemoveLinkHtml()
96 | {
97 | $src = Mage::getDesign()->getSkinUrl('images/rule_component_remove.gif');
98 | $html = '
';
99 |
100 | return $html;
101 | }
102 |
103 | //==================================================
104 | //=[ Serialization / Deserialization ]==============
105 | //==================================================
106 |
107 | public function toArray(array $attributes = [])
108 | {
109 | $out = [];
110 |
111 | foreach ($this->arrayKeys as $key) {
112 | $out[$key] = $this->getDataUsingMethod($key);
113 | }
114 |
115 | return $out;
116 | }
117 |
118 | public function loadArray(array $data)
119 | {
120 | if (isset($data['type'])) {
121 | if ($data['type'] != $this->getType()) {
122 | Mage::throwException('Invalid parameter');
123 | }
124 | unset($data['type']);
125 | }
126 |
127 | foreach ($this->arrayKeys as $key) {
128 | if (array_key_exists($key, $data)) {
129 | $this->setDataUsingMethod($key, $data[$key]);
130 | }
131 | }
132 |
133 | return $this;
134 | }
135 |
136 | //==================================================
137 | //=[ Extras ]=======================================
138 | //==================================================
139 |
140 | /**
141 | * Translate
142 | *
143 | * @return string
144 | */
145 | protected function translate()
146 | {
147 | if (!$this->moduleName) {
148 | $class = get_class($this);
149 | $this->moduleName = substr($class, 0, strpos($class, '_Model'));
150 | }
151 |
152 | $args = func_get_args();
153 | $expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->moduleName);
154 | array_unshift($args, $expr);
155 |
156 | return Mage::app()->getTranslator()->translate($args);
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/Abstract.php:
--------------------------------------------------------------------------------
1 | serializeFields($object);
13 | }
14 |
15 | /**
16 | * Serialize serializable fields of the object
17 | *
18 | * @param Mage_Core_Model_Abstract $object
19 | */
20 | public function serializeFields(Mage_Core_Model_Abstract $object)
21 | {
22 | foreach ($this->_serializableFields as $field => $parameters) {
23 | if (count($parameters) >= 2) {
24 | $serializeDefault = $parameters[0];
25 | if (count($parameters) > 3) {
26 | $unsetEmpty = (bool)$parameters[2];
27 | $callback = $parameters[3];
28 | } else {
29 | $unsetEmpty = isset($parameters[2]);
30 | $callback = null;
31 | }
32 | $this->_serializeField($object, $field, $serializeDefault, $unsetEmpty, $callback);
33 | }
34 | }
35 | }
36 |
37 |
38 | /**
39 | * Unserialize serializable object fields
40 | *
41 | * @param Mage_Core_Model_Abstract $object
42 | */
43 | public function unserializeFields(Mage_Core_Model_Abstract $object)
44 | {
45 | foreach ($this->_serializableFields as $field => $parameters) {
46 | if (count($parameters) >= 2) {
47 | $unserializeDefault = $parameters[1];
48 | if (count($parameters) > 4) {
49 | $callback = $parameters[4];
50 | } else {
51 | $callback = null;
52 | }
53 | $this->_unserializeField($object, $field, $unserializeDefault, $callback);
54 | }
55 | }
56 | }
57 |
58 | public static function implodeArray($value)
59 | {
60 | if (is_array($value)) {
61 | $value = implode(",", $value);
62 | } else {
63 | $value = (string)$value;
64 | }
65 |
66 | return $value;
67 | }
68 |
69 | public static function explodeArray($value)
70 | {
71 | if (is_string($value)) {
72 | $value = array_filter(array_map('trim', explode(",", $value)));
73 | } else {
74 | $value = [];
75 | }
76 |
77 | return $value;
78 | }
79 |
80 | /**
81 | * Serialize specified field in an object
82 | *
83 | * @param Varien_Object $object
84 | * @param string $field
85 | * @param null $defaultValue
86 | * @param bool $unsetEmpty
87 | * @param callable $callback
88 | *
89 | * @return $this
90 | */
91 | protected function _serializeField(Varien_Object $object, $field, $defaultValue = null, $unsetEmpty = false, $callback = null)
92 | {
93 | if (!is_callable($callback)) {
94 | $callback = 'serialize';
95 | }
96 |
97 | $value = $object->getData($field);
98 | if (empty($value)) {
99 | if ($unsetEmpty) {
100 | $object->unsetData($field);
101 | } else {
102 | if (is_object($defaultValue) || is_array($defaultValue)) {
103 | $defaultValue = call_user_func($callback, $defaultValue);
104 | }
105 | $object->setData($field, $defaultValue);
106 | }
107 | } elseif (is_array($value) || is_object($value)) {
108 | $object->setData($field, call_user_func($callback, $value));
109 | }
110 |
111 | return $this;
112 | }
113 |
114 | /**
115 | * Unserialize Varien_Object field in an object
116 | *
117 | * @param Varien_Object $object
118 | * @param string $field
119 | * @param mixed $defaultValue
120 | * @param callable $callback
121 | */
122 | protected function _unserializeField(Varien_Object $object, $field, $defaultValue = null, $callback = null)
123 | {
124 | if (!is_callable($callback)) {
125 | $callback = 'unserialize';
126 | }
127 |
128 | $value = $object->getData($field);
129 | if (empty($value)) {
130 | $object->setData($field, $defaultValue);
131 | } elseif (!is_array($value) && !is_object($value)) {
132 | $object->setData($field, call_user_func($callback, $value));
133 | }
134 | }
135 |
136 | /**
137 | * Prepare data for save
138 | *
139 | * @param Mage_Core_Model_Abstract $object
140 | *
141 | * @return array
142 | */
143 | protected function _prepareDataForSave(Mage_Core_Model_Abstract $object)
144 | {
145 | $currentTime = Varien_Date::now();
146 | if ((!$object->getId() || $object->isObjectNew()) && !$object->getCreatedAt()) {
147 | $object->setCreatedAt($currentTime);
148 | }
149 | $object->setUpdatedAt($currentTime);
150 | $data = parent::_prepareDataForSave($object);
151 |
152 | return $data;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/etc/adminhtml.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Set Fraud Flag
37 |
38 |
39 | Remove Fraud Flag
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | AOE Fraud Manager
51 | 35
52 |
53 |
54 | Blacklist Rules
55 | 100
56 |
57 |
58 | View
59 | 100
60 |
61 |
62 | Edit
63 | 200
64 |
65 |
66 | Test
67 | 300
68 |
69 |
70 |
71 |
72 | Hold Rules
73 | 200
74 |
75 |
76 | View
77 | 100
78 |
79 |
80 | Edit
81 | 200
82 |
83 |
84 | Test
85 | 300
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | AOE Fraud Manager
95 | 9999
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 1.1.0
6 |
7 |
8 |
9 |
10 |
11 | Aoe_FraudManager_Helper
12 |
13 |
14 |
15 |
16 | Aoe_FraudManager_Block
17 |
18 |
19 |
20 |
21 | Aoe_FraudManager_Model
22 | Aoe_FraudManager_Resource
23 |
24 |
25 | Aoe_FraudManager_Resource
26 |
27 |
28 | aoe_fraudmanager_blacklist_rule
29 |
30 |
31 | aoe_fraudmanager_hold_rule
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Aoe_FraudManager
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | aoe_fraudmanager/notification_email.txt
48 | txt
49 |
50 |
51 |
52 | aoe_fraudmanager/notification_email.txt
53 | txt
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | Aoe_FraudManager
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Aoe_FraudManager.csv
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Aoe_FraudManager.xml
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | Aoe_FraudManager/Observer
91 | addOrderConditions
92 |
93 |
94 |
95 |
96 |
97 |
98 | Aoe_FraudManager/Observer
99 | addOrderItemConditions
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Aoe_FraudManager/Observer
111 | checkQuoteSubmitBefore
112 |
113 |
114 |
115 |
116 |
117 |
118 | Aoe_FraudManager/Observer
119 | checkQuoteSubmitSuccess
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | An error occurred while placing your order.
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Helper/Condition.php:
--------------------------------------------------------------------------------
1 | getSkinUrl('images/rule_component_apply.gif');
10 | }
11 |
12 | public function getConditionApplyLabel()
13 | {
14 | return $this->__('Apply');
15 | }
16 |
17 | public function getOperators(array $filter = [])
18 | {
19 | if ($this->operators === null) {
20 | $this->operators = [
21 | '==' => $this->__('is'),
22 | '!=' => $this->__('is not'),
23 | '>=' => $this->__('equals or greater than'),
24 | '<=' => $this->__('equals or less than'),
25 | '>' => $this->__('greater than'),
26 | '<' => $this->__('less than'),
27 | '{}' => $this->__('contains'),
28 | '!{}' => $this->__('does not contain'),
29 | '()' => $this->__('is one of'),
30 | '!()' => $this->__('is not one of'),
31 | 'RE' => $this->__('matches regex pattern'),
32 | ];
33 | }
34 |
35 | if (empty($filter)) {
36 | return $this->operators;
37 | } else {
38 | $operators = $this->operators;
39 | $operators = array_intersect_key($operators, array_flip($filter));
40 |
41 | return $operators;
42 | }
43 | }
44 |
45 | /**
46 | * @param $operator
47 | * @param $expectedValue
48 | * @param $actualValue
49 | *
50 | * @return bool
51 | */
52 | public function validateValue($operator, $expectedValue, $actualValue)
53 | {
54 | $result = false;
55 | $invertResult = false;
56 |
57 | switch ($operator) {
58 | case '!=':
59 | $invertResult = true;
60 | // Fall-through
61 | case '==':
62 | if (is_array($expectedValue)) {
63 | if (is_array($actualValue)) {
64 | $result = array_intersect($expectedValue, $actualValue);
65 | $result = !empty($result);
66 | } else {
67 | return false;
68 | }
69 | } else {
70 | if (is_array($actualValue)) {
71 | $result = count($actualValue) == 1 && array_shift($actualValue) == $expectedValue;
72 | } else {
73 | $result = $this->compareValues($actualValue, $expectedValue);
74 | }
75 | }
76 | break;
77 |
78 | case '>':
79 | $invertResult = true;
80 | // Fall-through
81 | case '<=':
82 | if (!is_scalar($actualValue)) {
83 | return false;
84 | }
85 | $result = $actualValue <= $expectedValue;
86 | break;
87 |
88 | case '<':
89 | $invertResult = true;
90 | // Fall-through
91 | case '>=':
92 | if (!is_scalar($actualValue)) {
93 | return false;
94 | }
95 | $result = $actualValue >= $expectedValue;
96 | break;
97 |
98 | case '!{}':
99 | $invertResult = true;
100 | // Fall-through
101 | case '{}':
102 | // We don't support non-scalar values for the expected value on a 'contains' comparison
103 | if (!is_scalar($expectedValue)) {
104 | return false;
105 | }
106 | if (is_array($actualValue)) {
107 | foreach ($actualValue as $currentActualValue) {
108 | if ($this->compareValues($expectedValue, $currentActualValue, false)) {
109 | $result = true;
110 | break;
111 | }
112 | }
113 | } else {
114 | $result = $this->compareValues($expectedValue, $actualValue, false);
115 | }
116 | break;
117 |
118 | case '!()':
119 | $invertResult = true;
120 | // Fall-through
121 | case '()':
122 | if (is_array($actualValue)) {
123 | $result = (count(array_intersect($actualValue, (array)$expectedValue)) > 0);
124 | } else {
125 | $expectedValue = (array)$expectedValue;
126 | foreach ($expectedValue as $item) {
127 | if ($this->compareValues($item, $actualValue)) {
128 | $result = true;
129 | break;
130 | }
131 | }
132 | }
133 | break;
134 |
135 | case 'RE':
136 | $result = preg_match($expectedValue, $actualValue);
137 | if ($result === false) {
138 | Mage::throwException('Error running regex pattern (' . preg_last_error() . ').');
139 | }
140 | $result = (bool)$result;
141 | break;
142 | }
143 |
144 | if ($invertResult) {
145 | $result = !$result;
146 | }
147 |
148 | return $result;
149 | }
150 |
151 | /**
152 | * Case and type insensitive comparison of values
153 | *
154 | * @param string|int|float $expectedValue
155 | * @param string|int|float $actualValue
156 | *
157 | * @return bool
158 | */
159 | protected function compareValues($expectedValue, $actualValue, $strict = true)
160 | {
161 | if ($strict && is_numeric($expectedValue) && is_numeric($actualValue)) {
162 | return $expectedValue == $actualValue;
163 | } else {
164 | $validatePattern = preg_quote($expectedValue, '~');
165 | if ($strict) {
166 | $validatePattern = '^' . $validatePattern . '$';
167 | }
168 |
169 | return (bool)preg_match('~' . $validatePattern . '~iu', $actualValue);
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Helper/HoldRule.php:
--------------------------------------------------------------------------------
1 | getAdminSession()->isAllowed(self::ACL_PREFIX . trim($action, ' /'));
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getCurrentRecordKey()
40 | {
41 | return 'aoe_fraudmanager_hold_rule_CURRENT';
42 | }
43 |
44 | /**
45 | * Get a model instance
46 | *
47 | * @return Aoe_FraudManager_Model_HoldRule
48 | */
49 | public function getModel()
50 | {
51 | return Mage::getModel('Aoe_FraudManager/HoldRule');
52 | }
53 |
54 | /**
55 | * @return Varien_Data_Form
56 | */
57 | public function getMainForm($rule = null)
58 | {
59 | $form = parent::getMainForm($rule);
60 |
61 | /** @var Aoe_FraudManager_Model_HoldRule $rule */
62 | if (!$rule) {
63 | $rule = $this->getCurrentRecord();
64 | }
65 |
66 | /** @var Varien_Data_Form_Element_Fieldset $fieldset */
67 | $fieldset = $form->getElement('base_fieldset');
68 |
69 | $fieldset->addField(
70 | 'status',
71 | 'select',
72 | [
73 | 'label' => $this->__('Status'),
74 | 'title' => $this->__('Status'),
75 | 'name' => 'status',
76 | 'required' => true,
77 | 'options' => $this->getSourceModelHash('Aoe_FraudManager/Config_Source_Order_HoldStatuses'),
78 | ],
79 | 'description'
80 | );
81 |
82 | $form->addValues($rule->getData());
83 |
84 | return $form;
85 | }
86 |
87 | /**
88 | * Test an order against all of the rules
89 | *
90 | * @param Mage_Sales_Model_Order $order
91 | *
92 | * @return Varien_Data_Collection
93 | */
94 | public function testOrder(Mage_Sales_Model_Order $order)
95 | {
96 | $collection = new Varien_Data_Collection();
97 |
98 | /** @var Aoe_FraudManager_Resource_HoldRule_Collection $rules */
99 | $rules = Mage::getSingleton('Aoe_FraudManager/HoldRule')
100 | ->getCollection()
101 | ->filterValidForOrder($order, true);
102 |
103 | /** @var Mage_Sales_Model_Order_Config $salesConfig */
104 | $salesConfig = Mage::getSingleton('sales/order_config');
105 |
106 | $skip = false;
107 | foreach ($rules as $rule) {
108 | /** @var Aoe_FraudManager_Model_HoldRule $rule */
109 |
110 | $timing = microtime(true);
111 | $rule->setData('triggered', $rule->validate($order));
112 | $timing = microtime(true) - $timing;
113 |
114 | $rule->setData('timing', round($timing * 1000));
115 |
116 | $status = $rule->getData('status');
117 | $allowedStatuses = $salesConfig->getStateStatuses(Mage_Sales_Model_Order::STATE_HOLDED, false);
118 | if (!in_array($status, $allowedStatuses)) {
119 | $status = $salesConfig->getStateDefaultStatus(Mage_Sales_Model_Order::STATE_HOLDED);
120 | }
121 | $rule->setData('status', $status);
122 |
123 | $rule->setData('skipped', $skip);
124 |
125 | $collection->addItem($collection->getNewEmptyItem()->setData($rule->toArray()));
126 |
127 | $skip = $skip || ((bool)$rule->getData('stop_processing') && $rule->getData('triggered'));
128 | }
129 |
130 | return $collection;
131 | }
132 |
133 | /**
134 | * Email notification for hold rule activation
135 | *
136 | * @param string $message
137 | * @param array $extraVariables
138 | * @param int|string|null $store
139 | *
140 | * @return $this
141 | */
142 | public function notify($message, array $extraVariables = [], $store = null)
143 | {
144 | $store = Mage::app()->getStore($store);
145 |
146 | // Sender identity code
147 | $sender = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_SENDER, $store);
148 | if (!$sender) {
149 | return $this;
150 | }
151 |
152 | // Receiver identity code
153 | $receiver = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_RECEIVER, $store);
154 | if (!$receiver) {
155 | return $this;
156 | }
157 |
158 | // Template ID
159 | $templateId = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_TEMPLATE, $store);
160 | if (!$templateId) {
161 | return $this;
162 | }
163 |
164 | /** @var Mage_Core_Model_Email_Info $emailInfo */
165 | $emailInfo = Mage::getModel('core/email_info');
166 | $emailInfo->addTo(
167 | Mage::getStoreConfig("trans_email/ident_{$receiver}/email", $store),
168 | Mage::getStoreConfig("trans_email/ident_{$receiver}/name", $store)
169 | );
170 |
171 | /** @var $mailer Mage_Core_Model_Email_Template_Mailer */
172 | $mailer = Mage::getModel('core/email_template_mailer');
173 | $mailer->addEmailInfo($emailInfo);
174 |
175 | // Set all required params and send emails
176 | $mailer->setStoreId($store->getId());
177 | $mailer->setSender($sender);
178 | $mailer->setTemplateId($templateId);
179 | $mailer->setTemplateParams($extraVariables + ['message' => $message]);
180 | $mailer->send();
181 |
182 | return $this;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Helper/BlacklistRule.php:
--------------------------------------------------------------------------------
1 | getStore($store);
26 |
27 | /** @var Varien_Filter_Template $filter */
28 | $filter = Mage::getModel(Mage::getStoreConfig(self::XML_PATH_FILTER_MODEL, $store));
29 | if (!$filter instanceof Varien_Filter_Template) {
30 | $filter = Mage::getModel('core/email_template_filter');
31 | }
32 | if (method_exists($filter, 'setStoreId')) {
33 | $filter->setStoreId($store->getId());
34 | }
35 |
36 | return $filter->filter($message);
37 | }
38 |
39 | /**
40 | * Get the frontname and controller portion of the route
41 | *
42 | * @return string
43 | */
44 | protected function getControllerRoute()
45 | {
46 | return 'adminhtml/fraudManager_blacklistRule';
47 | }
48 |
49 | /**
50 | * @param $action
51 | *
52 | * @return bool
53 | */
54 | public function getAclPermission($action)
55 | {
56 | return $this->getAdminSession()->isAllowed(self::ACL_PREFIX . trim($action, ' /'));
57 | }
58 |
59 | /**
60 | * @return string
61 | */
62 | public function getCurrentRecordKey()
63 | {
64 | return 'aoe_fraudmanager_blacklist_rule_CURRENT';
65 | }
66 |
67 | /**
68 | * Get a model instance
69 | *
70 | * @return Aoe_FraudManager_Model_BlacklistRule
71 | */
72 | public function getModel()
73 | {
74 | return Mage::getModel('Aoe_FraudManager/BlacklistRule');
75 | }
76 |
77 | /**
78 | * @return Varien_Data_Form
79 | */
80 | public function getMainForm($rule = null)
81 | {
82 | $form = parent::getMainForm($rule);
83 |
84 | /** @var Aoe_FraudManager_Model_BlacklistRule $rule */
85 | if (!$rule) {
86 | $rule = $this->getCurrentRecord();
87 | }
88 |
89 | /** @var Varien_Data_Form_Element_Fieldset $fieldset */
90 | $fieldset = $form->getElement('base_fieldset');
91 |
92 | $fieldset->addField(
93 | 'message',
94 | 'textarea',
95 | [
96 | 'name' => 'message',
97 | 'label' => $this->__('Message'),
98 | 'title' => $this->__('Message'),
99 | 'comment' => $this->__('Message sent to customer when this rule is activated'),
100 | 'style' => 'height: 100px;',
101 | 'required' => false,
102 | ],
103 | 'description'
104 | );
105 |
106 | $form->addValues($rule->getData());
107 |
108 | return $form;
109 | }
110 |
111 | /**
112 | * Test an order against all of the rules
113 | *
114 | * @param Mage_Sales_Model_Order $order
115 | *
116 | * @return Varien_Data_Collection
117 | */
118 | public function testOrder(Mage_Sales_Model_Order $order)
119 | {
120 | $collection = new Varien_Data_Collection();
121 |
122 | /** @var Aoe_FraudManager_Helper_BlacklistRule $helper */
123 | $helper = Mage::helper('Aoe_FraudManager/BlacklistRule');
124 |
125 | /** @var Aoe_FraudManager_Resource_BlacklistRule_Collection $rules */
126 | $rules = Mage::getSingleton('Aoe_FraudManager/BlacklistRule')
127 | ->getCollection()
128 | ->filterValidForOrder($order, true);
129 |
130 | foreach ($rules as $rule) {
131 | /** @var Aoe_FraudManager_Model_BlacklistRule $rule */
132 |
133 | $timing = microtime(true);
134 | $rule->setData('triggered', $rule->validate($order));
135 | $timing = microtime(true) - $timing;
136 |
137 | $rule->setData('timing', round($timing * 1000));
138 |
139 | $message = $rule->getData('message');
140 | if (empty($message)) {
141 | $message = $helper->getDefaultMessage($order->getStoreId());
142 | }
143 | $rule->setData('message', $message);
144 |
145 | $collection->addItem($collection->getNewEmptyItem()->setData($rule->toArray()));
146 | }
147 |
148 | return $collection;
149 | }
150 |
151 | /**
152 | * Email notification for blacklist activation
153 | *
154 | * @param string $message
155 | * @param array $extraVariables
156 | * @param int|string|null $store
157 | *
158 | * @return $this
159 | */
160 | public function notify($message, array $extraVariables = [], $store = null)
161 | {
162 | $store = Mage::app()->getStore($store);
163 |
164 | // Sender identity code
165 | $sender = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_SENDER, $store);
166 | if (!$sender) {
167 | return $this;
168 | }
169 |
170 | // Receiver identity code
171 | $receiver = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_RECEIVER, $store);
172 | if (!$receiver) {
173 | return $this;
174 | }
175 |
176 | // Template ID
177 | $templateId = Mage::getStoreConfig(self::XML_PATH_NOTIFICATION_EMAIL_TEMPLATE, $store);
178 | if (!$templateId) {
179 | return $this;
180 | }
181 |
182 | /** @var Mage_Core_Model_Email_Info $emailInfo */
183 | $emailInfo = Mage::getModel('core/email_info');
184 | $emailInfo->addTo(
185 | Mage::getStoreConfig("trans_email/ident_{$receiver}/email", $store),
186 | Mage::getStoreConfig("trans_email/ident_{$receiver}/name", $store)
187 | );
188 |
189 | /** @var $mailer Mage_Core_Model_Email_Template_Mailer */
190 | $mailer = Mage::getModel('core/email_template_mailer');
191 | $mailer->addEmailInfo($emailInfo);
192 |
193 | // Set all required params and send emails
194 | $mailer->setStoreId($store->getId());
195 | $mailer->setSender($sender);
196 | $mailer->setTemplateId($templateId);
197 | $mailer->setTemplateParams($extraVariables + ['message' => $message]);
198 | $mailer->send();
199 |
200 | return $this;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Resource/Collection/Abstract.php:
--------------------------------------------------------------------------------
1 | _items as $item) {
15 | /** @var Mage_Core_Model_Abstract $item */
16 | $this->getResource()->unserializeFields($item);
17 | $item->afterLoad();
18 | $item->setOrigData();
19 | if ($this->_resetItemsDataChanged) {
20 | $item->setDataChanges(false);
21 | }
22 | }
23 |
24 | Mage::dispatchEvent('core_collection_abstract_load_after', ['collection' => $this]);
25 |
26 | if ($this->_eventPrefix && $this->_eventObject) {
27 | Mage::dispatchEvent($this->_eventPrefix . '_load_after', [$this->_eventObject => $this]);
28 | }
29 |
30 | return $this;
31 | }
32 |
33 | /**
34 | * Join table to collection select
35 | *
36 | * @param string $table
37 | * @param string $cond
38 | * @param string $cols
39 | *
40 | * @return Mage_Core_Model_Resource_Db_Collection_Abstract
41 | */
42 | public function join($table, $cond, $cols = '*')
43 | {
44 | if (is_array($table)) {
45 | foreach ($table as $k => $v) {
46 | $alias = $k;
47 | $table = $v;
48 | break;
49 | }
50 | } else {
51 | $alias = $table;
52 | }
53 |
54 | if (!isset($this->_joinedTables[$alias])) {
55 | $this->getSelect()->join(
56 | [$alias => $this->getTable($table)],
57 | $cond,
58 | $cols
59 | );
60 | $this->_joinedTables[$alias] = true;
61 | }
62 |
63 | return $this;
64 | }
65 |
66 | /**
67 | * Join table to collection select
68 | *
69 | * @param string $table
70 | * @param string $cond
71 | * @param string $cols
72 | *
73 | * @return Mage_Core_Model_Resource_Db_Collection_Abstract
74 | */
75 | public function joinLeft($table, $cond, $cols = '*')
76 | {
77 | if (is_array($table)) {
78 | foreach ($table as $k => $v) {
79 | $alias = $k;
80 | $table = $v;
81 | break;
82 | }
83 | } else {
84 | $alias = $table;
85 | }
86 |
87 | if (!isset($this->_joinedTables[$alias])) {
88 | $this->getSelect()->joinLeft(
89 | [$alias => $this->getTable($table)],
90 | $cond,
91 | $cols
92 | );
93 | $this->_joinedTables[$alias] = true;
94 | }
95 |
96 | return $this;
97 | }
98 |
99 | /**
100 | * Get SQL for get record count
101 | *
102 | * NB: This varies from standard Magento in that is uses a sub-select if grouping is being used
103 | *
104 | * @return Varien_Db_Select
105 | */
106 | public function getSelectCountSql()
107 | {
108 | $this->_renderFilters();
109 |
110 | $countSelect = clone $this->getSelect();
111 | $countSelect->reset(Zend_Db_Select::ORDER);
112 | $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
113 | $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
114 |
115 | // Fix problem with mixing COUNT and GROUP BY or HAVING
116 | $groups = $countSelect->getPart(Zend_Db_Select::GROUP);
117 | $having = $countSelect->getPart(Zend_Db_Select::HAVING);
118 | if (count($groups) || count($having)) {
119 | $countSelect = $this->_conn->select()->from($countSelect, 'COUNT(*)');
120 | } else {
121 | $countSelect->reset(Zend_Db_Select::COLUMNS);
122 | $countSelect->columns('COUNT(*)');
123 | }
124 |
125 | return $countSelect;
126 | }
127 |
128 | /**
129 | * Add filter to Map
130 | *
131 | * @param string $filter
132 | * @param string $alias
133 | * @param string $group default 'fields'
134 | *
135 | * @return Varien_Data_Collection_Db
136 | */
137 | public function addFilterToMap($filter, $alias, $group = 'fields')
138 | {
139 | if (is_null($this->_map)) {
140 | $this->_map = [$group => []];
141 | } else {
142 | if (!isset($this->_map[$group])) {
143 | $this->_map[$group] = [];
144 | }
145 | }
146 | $this->_map[$group][$filter] = $alias;
147 |
148 | return $this;
149 | }
150 |
151 | public function addFilterToHavingMap($filter)
152 | {
153 | return $this->addFilterToMap($filter, true, 'having');
154 | }
155 |
156 | /**
157 | * Add field filter to collection
158 | *
159 | * @see self::_getConditionSql for $condition
160 | *
161 | * @param string|array $field
162 | * @param null|string|array $condition
163 | * @param bool $having
164 | *
165 | * @return Mage_Eav_Model_Entity_Collection_Abstract
166 | */
167 | public function addFieldToFilter($field, $condition = null, $having = false)
168 | {
169 | $mapper = $this->_getMapper();
170 | if (!is_array($field)) {
171 | if (isset($mapper['having'][$field])) {
172 | $having = true;
173 | }
174 | $resultCondition = $this->_translateCondition($field, $condition);
175 | } else {
176 | $conditions = [];
177 | foreach ($field as $key => $currField) {
178 | if (isset($mapper['having'][$currField])) {
179 | $having = true;
180 | }
181 | $conditions[] = $this->_translateCondition(
182 | $currField,
183 | isset($condition[$key]) ? $condition[$key] : null
184 | );
185 | }
186 |
187 | $resultCondition = '(' . join(') ' . Zend_Db_Select::SQL_OR . ' (', $conditions) . ')';
188 | }
189 |
190 | if ($having) {
191 | $this->_select->having($resultCondition);
192 | } else {
193 | $this->_select->where($resultCondition);
194 | }
195 |
196 | return $this;
197 | }
198 |
199 | /**
200 | * @inheritdoc
201 | */
202 | protected function _toOptionArray($valueField = null, $labelField = 'name', $additional = [])
203 | {
204 | if ($valueField === null) {
205 | $valueField = $this->getResource()->getIdFieldName();
206 | if ($valueField === null) {
207 | $valueField = 'id';
208 | }
209 | }
210 |
211 | return parent::_toOptionArray($valueField, $labelField, $additional);
212 | }
213 |
214 | /**
215 | * @inheritdoc
216 | */
217 | protected function _toOptionHash($valueField = null, $labelField = 'name')
218 | {
219 | if ($valueField === null) {
220 | $valueField = $this->getResource()->getIdFieldName();
221 | if ($valueField === null) {
222 | $valueField = 'id';
223 | }
224 | }
225 |
226 | return parent::_toOptionHash($valueField, $labelField);
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Helper/FraudFlag.php:
--------------------------------------------------------------------------------
1 | resolveOrder($order);
18 | if (!$order instanceof Mage_Sales_Model_Order || $order->isObjectNew()) {
19 | return false;
20 | }
21 |
22 | if (!$this->isActive($order->getStoreId())) {
23 | return false;
24 | }
25 |
26 | return Mage::getStoreConfigFlag(self::XML_PATH_COMMENT_REQUIRED, $order->getStoreId());
27 | }
28 |
29 | public function isRemoveFlagCommentRequired($order = null)
30 | {
31 | $order = $this->resolveOrder($order);
32 | if (!$order instanceof Mage_Sales_Model_Order || $order->isObjectNew()) {
33 | return false;
34 | }
35 |
36 | if (!$this->isActive($order->getStoreId())) {
37 | return false;
38 | }
39 |
40 | return Mage::getStoreConfigFlag(self::XML_PATH_COMMENT_REQUIRED, $order->getStoreId());
41 | }
42 |
43 | public function getAutoHoldStatus($store = null)
44 | {
45 | return Mage::getStoreConfig(self::XML_PATH_AUTO_HOLD_STATUS, $store);
46 | }
47 |
48 | public function isFlagged($order = null)
49 | {
50 | $order = $this->resolveOrder($order);
51 |
52 | if ($order instanceof Mage_Sales_Model_Order && (bool)$order->getIsFraud()) {
53 | return true;
54 | }
55 |
56 | return false;
57 | }
58 |
59 | public function isSetFlagActionAllowed($order = null)
60 | {
61 | $order = $this->resolveOrder($order);
62 | if (!$order instanceof Mage_Sales_Model_Order || $order->isObjectNew()) {
63 | return false;
64 | }
65 |
66 | if (!$this->isActive($order->getStoreId())) {
67 | return false;
68 | }
69 |
70 | if ($this->isFlagged($order)) {
71 | return false;
72 | }
73 |
74 | return $this->getAdminSession()->isAllowed(self::ACL_PREFIX . 'set_fraud_flag');
75 | }
76 |
77 | public function isRemoveFlagActionAllowed($order = null)
78 | {
79 | $order = $this->resolveOrder($order);
80 | if (!$order instanceof Mage_Sales_Model_Order || $order->isObjectNew()) {
81 | return false;
82 | }
83 |
84 | if (!$this->isActive($order->getStoreId())) {
85 | return false;
86 | }
87 |
88 | if (!$this->isFlagged($order)) {
89 | return false;
90 | }
91 |
92 | return $this->getAdminSession()->isAllowed(self::ACL_PREFIX . 'remove_fraud_flag');
93 | }
94 |
95 | public function getSetFlagUrl($order = null)
96 | {
97 | $order = $this->resolveOrder($order);
98 |
99 | if ($order instanceof Mage_Sales_Model_Order && $order->getId()) {
100 | return $this->getUrl('adminhtml/sales_order/setFraudFlag', ['order_id' => $order->getId()]);
101 | }
102 |
103 | return false;
104 | }
105 |
106 | public function getRemoveFlagUrl($order = null)
107 | {
108 | $order = $this->resolveOrder($order);
109 |
110 | if ($order instanceof Mage_Sales_Model_Order && $order->getId()) {
111 | return $this->getUrl('adminhtml/sales_order/removeFraudFlag', ['order_id' => $order->getId()]);
112 | }
113 |
114 | return false;
115 | }
116 |
117 | public function setFlag($order = null, $message = '')
118 | {
119 | $order = $this->resolveOrder($order);
120 |
121 | if ($order instanceof Mage_Sales_Model_Order && $order->getId() && !$order->getIsFraud()) {
122 | $order->setIsFraud(1);
123 | $comment = trim($this->__('Marked order as fraud') . "\n\n" . $message);
124 | $holdStatus = $this->getAutoHoldStatus($order->getStore());
125 | if ($holdStatus && $order->canHold()) {
126 | $order->setHoldBeforeState($order->getState());
127 | $order->setHoldBeforeStatus($order->getStatus());
128 | $order->setState(Mage_Sales_Model_Order::STATE_HOLDED, $holdStatus, $comment);
129 | } else {
130 | $order->addStatusHistoryComment($comment);
131 | }
132 | $order->save();
133 |
134 | return true;
135 | }
136 |
137 | return false;
138 | }
139 |
140 | public function removeFlag($order = null, $message = '')
141 | {
142 | $order = $this->resolveOrder($order);
143 |
144 | if ($order instanceof Mage_Sales_Model_Order && $order->getId() && $order->getIsFraud()) {
145 | $order->setIsFraud(0);
146 | $comment = trim($this->__('Marked order as NOT fraud') . "\n\n" . $message);
147 | $holdStatus = $this->getAutoHoldStatus($order->getStore());
148 | if ($holdStatus && $order->canUnhold() && $order->getStatus() === $holdStatus) {
149 | $order->setState($order->getHoldBeforeState(), $order->getHoldBeforeStatus(), $comment);
150 | $order->setHoldBeforeState(null);
151 | $order->setHoldBeforeStatus(null);
152 | } else {
153 | $order->addStatusHistoryComment($comment);
154 | }
155 | $order->save();
156 |
157 | return true;
158 | }
159 |
160 | return false;
161 | }
162 |
163 | public function getCommentForm($order = null)
164 | {
165 | $order = $this->resolveOrder($order);
166 | if (!$order instanceof Mage_Sales_Model_Order) {
167 | return null;
168 | }
169 |
170 | $form = new Varien_Data_Form();
171 | $form->setId('edit_form');
172 | $form->setMethod('post');
173 | $form->setUseContainer(true);
174 |
175 | $fieldset = $form->addFieldset('base_fieldset', ['legend' => $this->__('Order')]);
176 |
177 | $fieldset->addField(
178 | 'comment',
179 | 'textarea',
180 | [
181 | 'id' => 'comment',
182 | 'name' => 'comment',
183 | 'label' => $this->__('Comment'),
184 | 'class' => 'required-entry',
185 | 'required' => true,
186 | ]
187 | );
188 |
189 | return $form;
190 | }
191 |
192 | /**
193 | * Return the current order or an empty order
194 | *
195 | * @return Mage_Sales_Model_Order
196 | */
197 | public function getCurrentOrder()
198 | {
199 | $order = Mage::registry('current_order');
200 | if ($order instanceof Mage_Sales_Model_Order) {
201 | return $order;
202 | } else {
203 | Mage::getModel('sales/order');
204 | }
205 | }
206 |
207 | /**
208 | *
209 | * @param Mage_Sales_Model_Order $order
210 | *
211 | * @return $this
212 | */
213 | public function setCurrentOrder(Mage_Sales_Model_Order $order = null)
214 | {
215 | Mage::unregister('sales_order');
216 | Mage::unregister('current_order');
217 |
218 | Mage::register('sales_order', $order);
219 | Mage::register('current_order', $order);
220 |
221 | return $this;
222 | }
223 |
224 | protected function resolveOrder($order = null)
225 | {
226 | if ($order instanceof Mage_Sales_Model_Order) {
227 | return $order;
228 | } elseif ($order) {
229 | return Mage::getModel('sales/order')->load($order);
230 | } else {
231 | return $this->getCurrentOrder();
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/etc/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | service
7 | text
8 | 9999
9 | 1
10 | 1
11 | 1
12 |
13 |
14 |
15 | text
16 | 100
17 | 1
18 | 1
19 | 1
20 |
21 |
22 |
23 | select
24 | adminhtml/system_config_source_yesno
25 | 100
26 | 1
27 | 1
28 | 1
29 |
30 |
31 |
32 | select
33 | adminhtml/system_config_source_yesno
34 | 200
35 | 1
36 | 1
37 | 1
38 |
39 |
40 |
41 | select
42 | Aoe_FraudManager/Config_Source_Order_HoldStatusesNone
43 | 300
44 | 1
45 | 1
46 | 1
47 |
48 |
49 |
50 |
51 |
52 | text
53 | 200
54 | 1
55 | 1
56 | 1
57 |
58 |
59 |
60 | select
61 | adminhtml/system_config_source_yesno
62 | 100
63 | 1
64 | 1
65 | 1
66 |
67 |
68 |
69 | select
70 | adminhtml/system_config_source_email_template
71 | 200
72 | 1
73 | 1
74 | 1
75 |
76 |
77 |
78 | select
79 | adminhtml/system_config_source_email_identity
80 | 210
81 | 1
82 | 1
83 | 1
84 |
85 |
86 |
87 | select
88 | adminhtml/system_config_source_email_identity
89 | 220
90 | 1
91 | 1
92 | 1
93 |
94 |
95 |
96 | textarea
97 | 300
98 | 1
99 | 1
100 | 1
101 |
102 |
103 |
104 |
105 |
106 | text
107 | 300
108 | 1
109 | 1
110 | 1
111 |
112 |
113 |
114 | select
115 | adminhtml/system_config_source_yesno
116 | 100
117 | 1
118 | 1
119 | 1
120 |
121 |
122 |
123 | select
124 | adminhtml/system_config_source_email_template
125 | 200
126 | 1
127 | 1
128 | 1
129 |
130 |
131 |
132 | select
133 | adminhtml/system_config_source_email_identity
134 | 210
135 | 1
136 | 1
137 | 1
138 |
139 |
140 |
141 | select
142 | adminhtml/system_config_source_email_identity
143 | 220
144 | 1
145 | 1
146 | 1
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Helper/AbstractRule.php:
--------------------------------------------------------------------------------
1 | getCollection();
8 | }
9 |
10 | /**
11 | * @return Varien_Data_Form
12 | */
13 | public function getForm($rule = null)
14 | {
15 | /** @var Aoe_FraudManager_Model_Rule_Abstract $rule */
16 | if (!$rule) {
17 | $rule = $this->getCurrentRecord();
18 | }
19 |
20 | $form = new Varien_Data_Form(
21 | [
22 | 'id' => 'edit_form',
23 | 'action' => $this->getEditUrl($rule),
24 | 'method' => 'post',
25 | 'use_container' => true,
26 | ]
27 | );
28 |
29 | return $form;
30 | }
31 |
32 | /**
33 | * @return Varien_Data_Form
34 | */
35 | public function getMainForm($rule = null)
36 | {
37 | /** @var Aoe_FraudManager_Model_Rule_Abstract $rule */
38 | if (!$rule) {
39 | $rule = $this->getCurrentRecord();
40 | }
41 |
42 | $form = new Varien_Data_Form();
43 | $form->setHtmlIdPrefix('rule_');
44 |
45 | $fieldset = $form->addFieldset(
46 | 'base_fieldset',
47 | ['legend' => $this->__('General Information')]
48 | );
49 |
50 | $fieldset->addField(
51 | 'name',
52 | 'text',
53 | [
54 | 'name' => 'name',
55 | 'label' => $this->__('Rule Name'),
56 | 'title' => $this->__('Rule Name'),
57 | 'required' => true,
58 | ]
59 | );
60 |
61 | $fieldset->addField(
62 | 'description',
63 | 'textarea',
64 | [
65 | 'name' => 'description',
66 | 'label' => $this->__('Description'),
67 | 'title' => $this->__('Description'),
68 | 'style' => 'height: 100px;',
69 | ]
70 | );
71 |
72 | $fieldset->addField(
73 | 'stop_processing',
74 | 'select',
75 | [
76 | 'name' => 'stop_processing',
77 | 'label' => $this->__('Stop Processing'),
78 | 'title' => $this->__('Stop Processing'),
79 | 'comment' => $this->__('Stop further rules processing is this rule matches'),
80 | 'required' => true,
81 | 'options' => $this->getSourceModelHash('adminhtml/system_config_source_yesno'),
82 | ]
83 | );
84 |
85 | $fieldset->addField(
86 | 'is_active',
87 | 'select',
88 | [
89 | 'name' => 'is_active',
90 | 'label' => $this->__('Active'),
91 | 'title' => $this->__('Active'),
92 | 'required' => true,
93 | 'options' => $this->getSourceModelHash('adminhtml/system_config_source_yesno'),
94 | ]
95 | );
96 |
97 | if ($this->getIsSingleStoreMode()) {
98 | $websiteId = Mage::app()->getStore(true)->getWebsiteId();
99 | $fieldset->addField(
100 | 'website_ids',
101 | 'hidden',
102 | [
103 | 'name' => 'website_ids[]',
104 | 'value' => $websiteId,
105 | ]
106 | );
107 | $rule->setWebsiteIds($websiteId);
108 | } else {
109 | $fieldset->addField(
110 | 'website_ids',
111 | 'multiselect',
112 | [
113 | 'name' => 'website_ids[]',
114 | 'label' => $this->__('Websites'),
115 | 'title' => $this->__('Websites'),
116 | 'required' => true,
117 | 'values' => $this->getSourceModelArray('core/website', true),
118 | ]
119 | );
120 | }
121 |
122 | $fieldset->addField(
123 | 'sort_order',
124 | 'text',
125 | [
126 | 'name' => 'sort_order',
127 | 'label' => $this->__('Sort Order'),
128 | 'comment' => $this->__('High numbers are processed first'),
129 | ]
130 | );
131 |
132 | $form->addValues($rule->getData());
133 |
134 | return $form;
135 | }
136 |
137 | /**
138 | * @return Varien_Data_Form
139 | */
140 | public function getConditionsForm($rule = null)
141 | {
142 | /** @var Aoe_FraudManager_Model_Rule_Abstract $rule */
143 | if (!$rule) {
144 | $rule = $this->getCurrentRecord();
145 | }
146 |
147 | $form = new Varien_Data_Form();
148 |
149 | $form->setHtmlIdPrefix('rule_');
150 |
151 | $fieldset = $form->addFieldset('conditions_fieldset', ['legend' => $this->__('Apply the rule only if the following conditions are met')]);
152 |
153 | $renderer = clone $form->getFieldsetRenderer();
154 | $renderer->setTemplate('promo/fieldset.phtml');
155 | $renderer->setNewChildUrl($this->getUrl('*/*/condition', ['form' => $fieldset->getHtmlId()]));
156 | $fieldset->setRenderer($renderer);
157 |
158 | $conditionsElement = $fieldset->addField(
159 | 'conditions',
160 | 'text',
161 | [
162 | 'name' => 'conditions',
163 | 'label' => $this->__('Conditions'),
164 | 'title' => $this->__('Conditions'),
165 | ]
166 | );
167 | $conditionsElement->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Conditions'));
168 |
169 | $form->addValues(['conditions' => $rule->getConditions()]);
170 |
171 | return $form;
172 | }
173 |
174 | /**
175 | * @param array $original
176 | *
177 | * @return array
178 | */
179 | public function convertFlatToRecursive(array $original, array $keys)
180 | {
181 | $result = [];
182 |
183 | foreach ($original as $key => $value) {
184 | if (in_array($key, $keys) && is_array($value)) {
185 | foreach ($value as $id => $data) {
186 | $path = explode('--', $id);
187 | $node =& $result;
188 | for ($i = 0, $l = sizeof($path); $i < $l; $i++) {
189 | if (!isset($node[$key][$path[$i]])) {
190 | $node[$key][$path[$i]] = [];
191 | }
192 | $node =& $node[$key][$path[$i]];
193 | }
194 | foreach ($data as $k => $v) {
195 | $node[$k] = $v;
196 | }
197 | }
198 | } else {
199 | $result[$key] = $value;
200 | }
201 | }
202 |
203 | return $result;
204 | }
205 |
206 | public function getTestOrderUrl($order = null)
207 | {
208 | $order = $this->resolveOrder($order);
209 |
210 | if ($order instanceof Mage_Sales_Model_Order && $order->getId()) {
211 | return $this->getUrl($this->getControllerRoute() . '/testOrder', ['order_id' => $order->getId()]);
212 | }
213 |
214 | return false;
215 | }
216 |
217 | public function getOrderViewUrl($order = null)
218 | {
219 | $order = $this->resolveOrder($order);
220 |
221 | if ($order instanceof Mage_Sales_Model_Order && $order->getId()) {
222 | return $this->getUrl('*/sales_order/view', ['order_id' => $order->getId()]);
223 | }
224 |
225 | return false;
226 | }
227 |
228 | public function canTest()
229 | {
230 | return $this->getAclPermission('test');
231 | }
232 |
233 | /**
234 | * Return the current order or an empty order
235 | *
236 | * @return Mage_Sales_Model_Order
237 | */
238 | public function getCurrentOrder()
239 | {
240 | $order = Mage::registry('current_order');
241 | if ($order instanceof Mage_Sales_Model_Order) {
242 | return $order;
243 | } else {
244 | Mage::getModel('sales/order');
245 | }
246 | }
247 |
248 | /**
249 | *
250 | * @param Mage_Sales_Model_Order $order
251 | *
252 | * @return $this
253 | */
254 | public function setCurrentOrder(Mage_Sales_Model_Order $order = null)
255 | {
256 | Mage::unregister('sales_order');
257 | Mage::unregister('current_order');
258 |
259 | Mage::register('sales_order', $order);
260 | Mage::register('current_order', $order);
261 |
262 | return $this;
263 | }
264 |
265 | protected function resolveOrder($order = null)
266 | {
267 | if ($order instanceof Mage_Sales_Model_Order) {
268 | return $order;
269 | } elseif ($order) {
270 | return Mage::getModel('sales/order')->load($order);
271 | } else {
272 | return $this->getCurrentOrder();
273 | }
274 | }
275 |
276 | /**
277 | * Test an order against all of the rules
278 | *
279 | * @param Mage_Sales_Model_Order $order
280 | *
281 | * @return Varien_Data_Collection
282 | */
283 | abstract public function testOrder(Mage_Sales_Model_Order $order);
284 | }
285 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Observer.php:
--------------------------------------------------------------------------------
1 | getParent();
12 | if (!$parent instanceof Aoe_FraudManager_Model_Rule_Condition_Interface) {
13 | return;
14 | }
15 |
16 | /** @var Varien_Object $container */
17 | $container = $observer->getContainer();
18 | if (!$container instanceof Varien_Object) {
19 | return;
20 | }
21 |
22 | $conditions = $container->getConditions();
23 | if (!is_array($conditions)) {
24 | $conditions = [];
25 | }
26 |
27 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_Attribute $condition */
28 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_Attribute');
29 | $conditionName = $helper->__($condition->getName());
30 | foreach ($condition->getAttributeOptions() as $attribute => $label) {
31 | $conditions[$conditionName][$condition->getType() . '|' . $attribute] = $label;
32 | }
33 |
34 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_BillingAddress_Attribute $condition */
35 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_BillingAddress_Attribute');
36 | $conditionName = $helper->__($condition->getName());
37 | foreach ($condition->getAttributeOptions() as $attribute => $label) {
38 | $conditions[$conditionName][$condition->getType() . '|' . $attribute] = $label;
39 | }
40 |
41 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_ShippingAddress_Attribute $condition */
42 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_ShippingAddress_Attribute');
43 | $conditionName = $helper->__($condition->getName());
44 | foreach ($condition->getAttributeOptions() as $attribute => $label) {
45 | $conditions[$conditionName][$condition->getType() . '|' . $attribute] = $label;
46 | }
47 |
48 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_Address_Compare $condition */
49 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_Address_Compare');
50 | $conditionName = $helper->__($condition->getName());
51 | foreach ($condition->getAttributeOptions() as $attribute => $label) {
52 | $conditions[$conditionName][$condition->getType() . '|' . $attribute] = $label;
53 | }
54 |
55 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_Item_Found $condition */
56 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_Item_Found');
57 | $conditions[$condition->getType()] = $helper->__($condition->getName());
58 |
59 | $container->setConditions($conditions);
60 | }
61 |
62 | public function addOrderItemConditions(Varien_Event_Observer $observer)
63 | {
64 | /** @var Aoe_FraudManager_Helper_Data $helper */
65 | $helper = Mage::helper('Aoe_FraudManager/Data');
66 |
67 | /** @var Aoe_FraudManager_Model_Rule_Condition_Interface $parent */
68 | $parent = $observer->getData('parent');
69 | if (!$parent instanceof Aoe_FraudManager_Model_Rule_Condition_Interface) {
70 | return;
71 | }
72 |
73 | /** @var Varien_Object $container */
74 | $container = $observer->getData('container');
75 | if (!$container instanceof Varien_Object) {
76 | return;
77 | }
78 |
79 | $conditions = $container->getData('conditions');
80 | if (!is_array($conditions)) {
81 | $conditions = [];
82 | }
83 |
84 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_Item_Combine $condition */
85 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_Item_Combine');
86 | $conditions[$condition->getType()] = $helper->__($condition->getName());
87 |
88 | /** @var Aoe_FraudManager_Model_Rule_Condition_Order_Item_Attribute $condition */
89 | $condition = Mage::getModel('Aoe_FraudManager/Rule_Condition_Order_Item_Attribute');
90 | $conditionName = $helper->__($condition->getName());
91 | foreach ($condition->getAttributeOptions() as $attribute => $label) {
92 | $conditions[$conditionName][$condition->getType() . '|' . $attribute] = $label;
93 | }
94 |
95 | $container->setData('conditions', $conditions);
96 | }
97 |
98 | public function checkQuoteSubmitBefore(Varien_Event_Observer $observer)
99 | {
100 | /** @var Mage_Sales_Model_Order $order */
101 | $order = $observer->getOrder();
102 | if (!$order instanceof Mage_Sales_Model_Order) {
103 | return;
104 | }
105 |
106 | /** @var Aoe_FraudManager_Helper_BlacklistRule $helper */
107 | $helper = Mage::helper('Aoe_FraudManager/BlacklistRule');
108 | if (!$helper->isActive($order->getStoreId())) {
109 | return;
110 | }
111 |
112 | /** @var Aoe_FraudManager_Resource_BlacklistRule_Collection $rules */
113 | $rules = Mage::getSingleton('Aoe_FraudManager/BlacklistRule')
114 | ->getCollection()
115 | ->filterValidForOrder($order);
116 |
117 | $messages = [];
118 | $notifications = [];
119 | foreach ($rules as $rule) {
120 | /** @var Aoe_FraudManager_Model_BlacklistRule $rule */
121 | if ($rule->validate($order)) {
122 | $notification = sprintf('Preventing order due to rules check: %s / %s / %s', $rule->getName(), $order->getIncrementId(), $order->getQuoteId());
123 | $notifications[] = $notification;
124 | Mage::log($notification, Zend_Log::WARN, 'fraud.log');
125 |
126 | $message = $rule->getMessage();
127 | if (empty($message)) {
128 | $message = $helper->getDefaultMessage($order->getStoreId());
129 | }
130 |
131 | $messages[] = $helper->__($helper->filterMessage($message, $order->getStoreId()));
132 |
133 | if ($rule->getStopProcessing()) {
134 | break;
135 | }
136 | }
137 | }
138 |
139 | if (count($notifications)) {
140 | try {
141 | $helper->notify(implode("\n", $notifications), ['order' => $order], $order->getStoreId());
142 | } catch (Exception $e) {
143 | Mage::logException($e);
144 | }
145 | }
146 |
147 | if (count($messages)) {
148 | throw new Mage_Payment_Model_Info_Exception(nl2br(implode("\n", $messages)));
149 | }
150 | }
151 |
152 | public function checkQuoteSubmitSuccess(Varien_Event_Observer $observer)
153 | {
154 | /** @var Mage_Sales_Model_Order $order */
155 | $order = $observer->getOrder();
156 | if (!$order instanceof Mage_Sales_Model_Order) {
157 | return;
158 | }
159 |
160 | /** @var Aoe_FraudManager_Helper_HoldRule $helper */
161 | $helper = Mage::helper('Aoe_FraudManager/HoldRule');
162 | if (!$helper->isActive($order->getStoreId())) {
163 | return;
164 | }
165 |
166 | // Exit early if the order cannot be held
167 | if (!$order->canHold()) {
168 | return;
169 | }
170 |
171 | /** @var Aoe_FraudManager_Resource_HoldRule_Collection $rules */
172 | $rules = Mage::getSingleton('Aoe_FraudManager/HoldRule')
173 | ->getCollection()
174 | ->filterValidForOrder($order);
175 |
176 | $notifications = [];
177 | foreach ($rules as $rule) {
178 | /** @var Aoe_FraudManager_Model_HoldRule $rule */
179 | if ($rule->validate($order)) {
180 | $notification = sprintf('Holding order due to rules check: %s / %s / %s', $rule->getName(), $order->getIncrementId(), $order->getQuoteId());
181 | $notifications[] = $notification;
182 | Mage::log($notification, Zend_Log::INFO, 'fraud.log');
183 |
184 | if ($order->canHold()) {
185 | $order->setHoldBeforeState($order->getState());
186 | $order->setHoldBeforeStatus($order->getStatus());
187 | }
188 |
189 | $status = $rule->getStatus();
190 | /** @var Mage_Sales_Model_Order_Config $salesConfig */
191 | $salesConfig = Mage::getSingleton('sales/order_config');
192 | $allowedStatuses = $salesConfig->getStateStatuses(Mage_Sales_Model_Order::STATE_HOLDED, false);
193 | if (!in_array($status, $allowedStatuses)) {
194 | $status = true;
195 | }
196 |
197 | $order->setState(Mage_Sales_Model_Order::STATE_HOLDED, $status, sprintf('Holding order due to rules check: %s', $rule->getName()));
198 |
199 | if ($rule->getStopProcessing()) {
200 | break;
201 | }
202 | }
203 | }
204 |
205 | if (count($notifications)) {
206 | try {
207 | $helper->notify(implode("\n", $notifications), ['order' => $order], $order->getStoreId());
208 | } catch (Exception $e) {
209 | Mage::logException($e);
210 | }
211 | }
212 |
213 | $order->save();
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/aoe_fraudmanager/sales/order/view/info.phtml:
--------------------------------------------------------------------------------
1 |
27 | getOrder() ?>
28 | formatDate($_order->getCreatedAtDate(), 'medium', true);
30 | $orderStoreDate = $this->formatDate($_order->getCreatedAtStoreDate(), 'medium', true);
31 | ?>
32 |
33 |
34 |
35 | getEmailSent()):
36 | $_email = Mage::helper('sales')->__('the order confirmation email was sent');
37 | else:
38 | $_email = Mage::helper('sales')->__('the order confirmation email is not sent');
39 | endif; ?>
40 |
41 | getNoUseOrderLink()): ?>
42 |
__('Order # %s', $_order->getRealOrderId()) ?> ()
43 |
44 |
__('Order # %s', $_order->getRealOrderId()) ?>
45 |
()
46 |
47 |
48 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
__('Account Information') ?>
117 |
118 |
getAccountEditLink() ?>
119 |
120 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
__('Billing Address') ?>
161 |
162 |
getAddressEditLink($_order->getBillingAddress()) ?>
163 |
164 |
167 |
168 |
169 | getOrder()->getIsVirtual()): ?>
170 |
171 |
172 |
173 |
174 |
__('Shipping Address') ?>
175 |
176 |
getAddressEditLink($_order->getShippingAddress()) ?>
177 |
178 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Attribute.php:
--------------------------------------------------------------------------------
1 | arrayKeys[] = 'attribute';
20 | $this->arrayKeys[] = 'operator';
21 | $this->arrayKeys[] = 'value';
22 | }
23 |
24 | /**
25 | * @return array|false
26 | */
27 | public function getAttributeOptions()
28 | {
29 | if ($this->attributeOptions === null) {
30 | $this->attributeOptions = array_map([$this, 'translate'], array_map('reset', $this->attributes));
31 | if (empty($this->attributeOptions)) {
32 | $this->attributeOptions = false;
33 | }
34 | }
35 |
36 | return $this->attributeOptions;
37 | }
38 |
39 | /**
40 | * @return string|null
41 | */
42 | public function getAttribute()
43 | {
44 | return $this->getData('attribute');
45 | }
46 |
47 | /**
48 | * @param string $attribute
49 | *
50 | * @return $this
51 | */
52 | public function setAttribute($attribute)
53 | {
54 | return $this->setData('attribute', $attribute);
55 | }
56 |
57 | public function getAttributeName()
58 | {
59 | $attribute = $this->getAttribute();
60 |
61 | if (is_null($attribute) || '' === $attribute) {
62 | return '...';
63 | }
64 |
65 | $options = $this->getAttributeOptions();
66 | if ($options === false || empty($options)) {
67 | return $attribute;
68 | }
69 |
70 | if (array_key_exists($attribute, $options)) {
71 | return $options[$attribute];
72 | }
73 |
74 | return '';
75 | }
76 |
77 | /**
78 | * @return array
79 | */
80 | public function getOperatorOptions()
81 | {
82 | $allowedOperators = [];
83 | if (isset($this->attributes[$this->getAttribute()]) && isset($this->attributes[$this->getAttribute()][1])) {
84 | $allowedOperators = $this->attributes[$this->getAttribute()][1];
85 | }
86 |
87 | return Mage::helper('Aoe_FraudManager/Condition')->getOperators($allowedOperators);
88 | }
89 |
90 | /**
91 | * @return string|null
92 | */
93 | public function getOperator()
94 | {
95 | if (is_null($this->getData('operator'))) {
96 | $options = array_keys($this->getOperatorOptions());
97 | $this->setOperator(reset($options));
98 | }
99 |
100 | return $this->getData('operator');
101 | }
102 |
103 | /**
104 | * @param string $operator
105 | *
106 | * @return $this
107 | */
108 | public function setOperator($operator)
109 | {
110 | return $this->setData('operator', $operator);
111 | }
112 |
113 | /**
114 | * @return string
115 | */
116 | public function getOperatorName()
117 | {
118 | $options = $this->getOperatorOptions();
119 |
120 | return (isset($options[$this->getOperator()]) ? $options[$this->getOperator()] : '');
121 | }
122 |
123 | /**
124 | * Check if value should be array
125 | *
126 | * Depends on operator input type
127 | *
128 | * @return bool
129 | */
130 | public function getOperatorIsArrayType()
131 | {
132 | return in_array($this->getOperator(), $this->arrayOperators);
133 | }
134 |
135 | /**
136 | * @return array|false
137 | */
138 | public function getValueOptions()
139 | {
140 | return false;
141 | }
142 |
143 | /**
144 | * @return string|null
145 | */
146 | public function getValue()
147 | {
148 | return $this->getData('value');
149 | }
150 |
151 | /**
152 | * @param string $value
153 | *
154 | * @return $this
155 | */
156 | public function setValue($value)
157 | {
158 | return $this->setData('value', $value);
159 | }
160 |
161 | public function getValueParsed()
162 | {
163 | $value = $this->getValue();
164 |
165 | if ($this->getOperatorIsArrayType() && is_string($value)) {
166 | $value = preg_split('#\s*[,;]\s*#', $value, null, PREG_SPLIT_NO_EMPTY);
167 | }
168 |
169 | return $value;
170 | }
171 |
172 | public function getValueName()
173 | {
174 | $value = $this->getValue();
175 |
176 | if (is_null($value) || '' === $value) {
177 | return '...';
178 | }
179 |
180 | $options = $this->getValueOptions();
181 | if ($options === false) {
182 | return $value;
183 | }
184 |
185 | if (is_array($value)) {
186 | $valueLabels = [];
187 | foreach ($options as $k => $v) {
188 | if (in_array($k, $value)) {
189 | $valueLabels[] = $v;
190 | }
191 | }
192 |
193 | return implode(', ', $valueLabels);
194 | } elseif (array_key_exists($value, $options)) {
195 | return $options[$value];
196 | }
197 |
198 | return '';
199 | }
200 |
201 | //==================================================
202 | //=[ HTML Generation ]==============================
203 | //==================================================
204 |
205 | public function getConditionConfigHtml()
206 | {
207 | $html = $this->translate($this->getName()) . ' ';
208 | $html .= $this->getAttributeElement()->getHtml();
209 | $html .= $this->getOperatorElement()->getHtml();
210 | $html .= $this->getValueElement()->getHtml();
211 | $html .= $this->getChooserContainerHtml();
212 |
213 | return $html;
214 | }
215 |
216 | /**
217 | * @return Varien_Data_Form_Element_Abstract
218 | */
219 | public function getAttributeElement()
220 | {
221 | $attribute = $this->getAttribute();
222 | $options = $this->getAttributeOptions();
223 |
224 | if (is_array($options) && empty($attribute)) {
225 | $element = $this->getForm()->addField(
226 | $this->getId() . '__attribute',
227 | 'select',
228 | [
229 | 'name' => $this->getId() . '[attribute]',
230 | 'options' => $this->getAttributeOptions(),
231 | 'value' => $this->getAttribute(),
232 | 'label' => $this->getAttributeName(),
233 | ]
234 | );
235 | } else {
236 | $element = $this->getForm()->addField(
237 | $this->getId() . '__attribute',
238 | 'text',
239 | [
240 | 'name' => $this->getId() . '[attribute]',
241 | 'value' => $this->getAttribute(),
242 | 'label' => $this->getAttributeName(),
243 | 'show_as_text' => true,
244 | ]
245 | );
246 | }
247 |
248 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Editable'));
249 |
250 | return $element;
251 | }
252 |
253 | /**
254 | * @return Varien_Data_Form_Element_Abstract
255 | */
256 | public function getOperatorElement()
257 | {
258 | $element = $this->getForm()->addField(
259 | $this->getId() . '__operator',
260 | 'select',
261 | [
262 | 'name' => $this->getId() . '[operator]',
263 | 'options' => $this->getOperatorOptions(),
264 | 'value' => $this->getOperator(),
265 | 'label' => $this->getOperatorName(),
266 | ]
267 | );
268 |
269 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Editable'));
270 |
271 | return $element;
272 | }
273 |
274 |
275 | /**
276 | * Value element type will define renderer for condition value element
277 | *
278 | * @see Varien_Data_Form_Element
279 | * @return string
280 | */
281 | public function getValueElementType()
282 | {
283 | return 'text';
284 | }
285 |
286 | /**
287 | * Retrieve input type
288 | *
289 | * @return string
290 | */
291 | public function getValueElementInputType()
292 | {
293 | return 'string';
294 | }
295 |
296 | public function getValueElement()
297 | {
298 | $elementParams = [
299 | 'name' => $this->getId() . '[value]',
300 | 'value' => $this->getValue(),
301 | 'options' => $this->getValueOptions(),
302 | 'label' => $this->getValueName(),
303 | ];
304 |
305 | $options = $this->getValueOptions();
306 | if (is_array($options)) {
307 | $elementParams['options'] = $options;
308 | }
309 |
310 | if ($this->getValueElementType() == 'date') {
311 | // date format intentionally hard-coded
312 | $elementParams['input_format'] = Varien_Date::DATE_INTERNAL_FORMAT;
313 | $elementParams['format'] = Varien_Date::DATE_INTERNAL_FORMAT;
314 | }
315 |
316 | $element = $this->getForm()->addField($this->getId() . '__value', $this->getValueElementType(), $elementParams);
317 |
318 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Editable'));
319 |
320 | return $element;
321 | }
322 |
323 | public function getChooserContainerHtml()
324 | {
325 | $html = '';
326 |
327 | $url = $this->getValueElementChooserUrl();
328 | if ($url) {
329 | $html = '';
330 | }
331 |
332 | return $html;
333 | }
334 |
335 | public function validate(Varien_Object $object)
336 | {
337 | $attribute = $this->getAttribute();
338 | if (empty($attribute)) {
339 | return false;
340 | }
341 |
342 | return Mage::helper('Aoe_FraudManager/Condition')->validateValue($this->getOperator(), $this->getValueParsed(), $this->getAttributeValue($object));
343 | }
344 |
345 | protected function getAttributeValue(Varien_Object $object)
346 | {
347 | $attribute = $this->getAttribute();
348 | if (!empty($attribute)) {
349 | return $object->getDataUsingMethod($attribute);
350 | } else {
351 | return null;
352 | }
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/app/code/local/Aoe/FraudManager/Model/Rule/Condition/Combine.php:
--------------------------------------------------------------------------------
1 | setType('Aoe_FraudManager/Rule_Condition_Combine');
11 | $this->setName('Conditions Combination');
12 | $this->arrayKeys[] = 'aggregator';
13 | $this->arrayKeys[] = 'value';
14 | }
15 |
16 | /**
17 | * @return string
18 | */
19 | public function getSelfType()
20 | {
21 | return $this->getType();
22 | }
23 |
24 | /**
25 | * @return string|null
26 | */
27 | public function getAggregator()
28 | {
29 | if (is_null($this->getData('aggregator'))) {
30 | $options = array_keys($this->getAggregatorOptions());
31 | $this->setAggregator(reset($options));
32 | }
33 |
34 | return $this->getData('aggregator');
35 | }
36 |
37 | /**
38 | * @param string $aggregator
39 | *
40 | * @return $this;
41 | */
42 | public function setAggregator($aggregator)
43 | {
44 | return $this->setData('aggregator', $aggregator);
45 | }
46 |
47 | /**
48 | * @return string|null
49 | */
50 | public function getValue()
51 | {
52 | if (is_null($this->getData('value'))) {
53 | $options = array_keys($this->getValueOptions());
54 | $this->setValue(reset($options));
55 | }
56 |
57 | return $this->getData('value');
58 | }
59 |
60 | /**
61 | * @param string $value
62 | *
63 | * @return $this;
64 | */
65 | public function setValue($value)
66 | {
67 | return $this->setData('value', $value);
68 | }
69 |
70 | /**
71 | * @return Aoe_FraudManager_Model_Rule_Condition_Interface[]
72 | */
73 | public function getConditions()
74 | {
75 | if (!is_array($this->getData('conditions'))) {
76 | $this->setConditions([]);
77 | }
78 |
79 | return $this->getData('conditions');
80 | }
81 |
82 | /**
83 | * Set conditions, if current prefix is undefined use 'conditions' key
84 | *
85 | * @param Aoe_FraudManager_Model_Rule_Condition_Interface[] $conditions
86 | *
87 | * @return $this
88 | */
89 | public function setConditions(array $conditions)
90 | {
91 | return $this->setData('conditions', $conditions);
92 | }
93 |
94 | /**
95 | * @param Aoe_FraudManager_Model_Rule_Condition_Interface $condition
96 | *
97 | * @return $this
98 | */
99 | public function addCondition(Aoe_FraudManager_Model_Rule_Condition_Interface $condition)
100 | {
101 | $condition->setRule($this->getRule());
102 |
103 | $conditions = $this->getConditions();
104 | if (!$condition->getId()) {
105 | $id = uniqid($this->getId() . '--');
106 | while (isset($conditions[$id])) {
107 | $id = uniqid($this->getId() . '--');
108 | }
109 | $condition->setId($id);
110 | }
111 |
112 | $conditions[$condition->getId()] = $condition;
113 |
114 | $this->setConditions($conditions);
115 |
116 | return $this;
117 | }
118 |
119 | public function removeCondition(Aoe_FraudManager_Model_Rule_Condition_Interface $condition)
120 | {
121 | $conditions = $this->getConditions();
122 | unset($conditions[$condition->getId()]);
123 | $this->setConditions($conditions);
124 |
125 | return $this;
126 | }
127 |
128 | /**
129 | * @param Varien_Object $object
130 | *
131 | * @return bool
132 | */
133 | public function validate(Varien_Object $object)
134 | {
135 | $conditions = $this->getConditions();
136 |
137 | if (empty($conditions)) {
138 | return true;
139 | }
140 |
141 | $all = ($this->getAggregator() === 'all');
142 | $true = (bool)$this->getValue();
143 |
144 | foreach ($conditions as $condition) {
145 | $validated = $condition->validate($object);
146 | if ($all && $validated !== $true) {
147 | return false;
148 | } elseif (!$all && $validated === $true) {
149 | return true;
150 | }
151 | }
152 |
153 | return $all;
154 | }
155 |
156 | //==================================================
157 | //=[ HTML Generation ]==============================
158 | //==================================================
159 |
160 | public function getHtml()
161 | {
162 | $html = parent::getHtml();
163 |
164 | $htmlId = $this->getForm()->getHtmlIdPrefix() . $this->getId() . '__children' . $this->getForm()->getHtmlIdSuffix();
165 | $html .= '';
166 |
167 | foreach ($this->getConditions() as $condition) {
168 | $html .= '- ' . $condition->getHtml() . '
';
169 | }
170 |
171 | $html .= '- ' . $this->getNewChildElement()->getHtml() . '
';
172 |
173 | $html .= '
';
174 |
175 | return $html;
176 | }
177 |
178 | public function getConditionConfigHtml()
179 | {
180 | return $this->translate(
181 | 'If %s of these conditions are %s:',
182 | $this->getAggregatorElement()->getHtml(),
183 | $this->getValueElement()->getHtml()
184 | );
185 | }
186 |
187 | public function getAggregatorOptions()
188 | {
189 | $options = [
190 | 'all' => $this->translate('ALL'),
191 | 'any' => $this->translate('ANY'),
192 | ];
193 |
194 | return $options;
195 | }
196 |
197 | public function getAggregatorName()
198 | {
199 | $options = $this->getAggregatorOptions();
200 |
201 | return (isset($options[$this->getAggregator()]) ? $options[$this->getAggregator()] : '');
202 | }
203 |
204 | public function getAggregatorElement()
205 | {
206 | $element = $this->getForm()->addField(
207 | $this->getId() . '__aggregator',
208 | 'select',
209 | [
210 | 'name' => $this->getId() . '[aggregator]',
211 | 'value' => $this->getAggregator(),
212 | 'label' => $this->getAggregatorName(),
213 | 'options' => $this->getAggregatorOptions(),
214 | ]
215 | );
216 |
217 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Editable'));
218 |
219 | return $element;
220 | }
221 |
222 | public function getValueOptions()
223 | {
224 | $options = [
225 | '1' => $this->translate('TRUE'),
226 | '0' => $this->translate('FALSE'),
227 | ];
228 |
229 | return $options;
230 | }
231 |
232 | public function getValueName()
233 | {
234 | $options = $this->getValueOptions();
235 |
236 | return (isset($options[$this->getValue()]) ? $options[$this->getValue()] : '');
237 | }
238 |
239 | public function getValueElement()
240 | {
241 | $element = $this->getForm()->addField(
242 | $this->getId() . '__value',
243 | 'select',
244 | [
245 | 'name' => $this->getId() . '[value]',
246 | 'value' => $this->getValue(),
247 | 'label' => $this->getValueName(),
248 | 'options' => $this->getValueOptions(),
249 | ]
250 | );
251 |
252 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Editable'));
253 |
254 | return $element;
255 | }
256 |
257 | /**
258 | * Get conditions selectors
259 | *
260 | * @return array
261 | */
262 | public function getNewChildOptions()
263 | {
264 | $conditions = ['' => $this->translate('Please choose a condition to add...')];
265 |
266 | // Add self reference for recursive combinations
267 | $conditions[$this->getSelfType()] = $this->translate($this->getName());
268 |
269 | // Fire an event to add additional conditions
270 | $container = new Varien_Object();
271 | Mage::dispatchEvent('aoe_fraudmanager_rule_condition_combine_additional', ['parent' => $this, 'container' => $container]);
272 | if ($additional = $container->getConditions()) {
273 | $conditions = array_merge($conditions, $additional);
274 | }
275 |
276 | return $conditions;
277 | }
278 |
279 | public function getNewChildName()
280 | {
281 | return $this->translate('Add');
282 | }
283 |
284 | public function getNewChildElement()
285 | {
286 | $element = $this->getForm()->addField(
287 | $this->getId() . '__new_child',
288 | 'select',
289 | [
290 | 'name' => $this->getId() . '[new_child]',
291 | 'label' => $this->getNewChildName(),
292 | 'options' => $this->getNewChildOptions(),
293 | ]
294 | );
295 |
296 | $element->setRenderer(Mage::getSingleton('Aoe_FraudManager/Form_Element_Renderer_Newchild'));
297 |
298 | return $element;
299 | }
300 |
301 | //==================================================
302 | //=[ Serialization / Deserialization ]==============
303 | //==================================================
304 | public function toArray()
305 | {
306 | $out = parent::toArray();
307 |
308 | foreach ($this->getConditions() as $condition) {
309 | $out['conditions'][] = $condition->toArray();
310 | }
311 |
312 | return $out;
313 | }
314 |
315 | public function loadArray(array $data)
316 | {
317 | parent::loadArray($data);
318 |
319 | if (array_key_exists('conditions', $data) && is_array($data['conditions'])) {
320 | foreach ($data['conditions'] as $conditionData) {
321 | try {
322 | $modelClass = $conditionData['type'];
323 | if (empty($modelClass)) {
324 | continue;
325 | }
326 |
327 | $model = Mage::getSingleton($modelClass);
328 | if (!$model || !$model instanceof Aoe_FraudManager_Model_Rule_Condition_Interface) {
329 | continue;
330 | }
331 |
332 | $condition = clone $model;
333 | if ($condition) {
334 | $this->addCondition($condition);
335 | $condition->loadArray($conditionData);
336 | if ($condition instanceof Aoe_FraudManager_Model_Rule_Condition_Combine) {
337 | $conditions = $condition->getConditions();
338 | if (empty($conditions)) {
339 | $this->removeCondition($condition);
340 | }
341 | }
342 | }
343 | } catch (Exception $e) {
344 | Mage::logException($e);
345 | }
346 | }
347 | }
348 |
349 | return $this;
350 | }
351 | }
352 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/layout/Aoe_FraudManager.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | css/aoe_fraudmanager.css
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Blacklist Rules
17 |
18 |
19 |
20 | aoe_fraudmanager_blacklistrule_grid
21 |
22 |
23 | 1
24 |
25 |
26 |
27 |
28 |
29 | id
30 |
31 | id
32 | number
33 |
34 | 50px
35 | right
36 |
37 |
38 |
39 | name
40 |
41 |
42 | name
43 | text
44 |
45 |
46 |
47 | stop_processing
48 |
49 | stop_processing
50 |
51 | options
52 |
53 | adminhtml/system_config_source_yesno
54 |
55 |
56 |
57 |
58 | is_active
59 |
60 | is_active
61 |
62 | options
63 |
64 | adminhtml/system_config_source_yesno
65 |
66 |
67 |
68 |
69 | website_ids
70 |
71 | website_ids
72 |
73 | options
74 | 0
75 | 100px
76 |
77 | core/website
78 | 1
79 |
80 |
81 |
82 |
83 | sort_order
84 |
85 | sort_order
86 | number
87 |
88 | 50px
89 | right
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | {{id}}
98 |
99 |
100 |
101 | id
102 |
103 |
104 | desc
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | 1
120 |
121 |
122 | 1
123 |
124 |
125 |
126 |
127 |
128 | New Rule
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | aoe_fraudmanager_blacklistrule_edit_tabs
141 |
142 |
143 | edit_form
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | main
158 | main
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | conditions
170 | conditions
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | Edit Rule
181 |
182 |
183 | delete
184 |
185 |
186 |
187 | deleteConfirm('%s', '%s')
188 | Are you sure you want to do this?
189 |
190 |
191 |
192 |
193 | delete
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | Testing Order #%s Against All Blacklist Rules
205 |
206 |
207 | increment_id
208 |
209 |
210 |
211 |
212 | add
213 |
214 |
215 | back
216 |
217 |
218 |
219 | setLocation('%s')
220 |
221 |
222 | back
223 |
224 |
225 |
226 |
227 | aoe_fraudmanager_blacklistrule_testorder_grid
228 |
229 |
230 | 0
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | 0
239 |
240 |
241 | 0
242 |
243 |
244 | id
245 |
246 | id
247 | number
248 |
249 | 50px
250 | right
251 |
252 |
253 |
254 | name
255 |
256 |
257 | name
258 | text
259 |
260 |
261 |
262 | is_active
263 |
264 | is_active
265 |
266 | options
267 |
268 | adminhtml/system_config_source_yesno
269 |
270 |
271 |
272 |
273 | triggered
274 |
275 | triggered
276 |
277 | options
278 |
279 | adminhtml/system_config_source_yesno
280 |
281 |
282 |
283 |
284 | timing
285 |
286 | timing
287 | number
288 |
289 | 50px
290 | right
291 |
292 |
293 |
294 | message
295 |
296 | message
297 | text
298 |
299 | right
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 | {{id}}
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 | Hold Rules
321 |
322 |
323 |
324 | aoe_fraudmanager_holdrule_grid
325 |
326 |
327 | 1
328 |
329 |
330 |
331 |
332 |
333 | id
334 |
335 | id
336 | number
337 |
338 | 50px
339 | right
340 |
341 |
342 |
343 | name
344 |
345 |
346 | name
347 | text
348 |
349 |
350 |
351 | stop_processing
352 |
353 | stop_processing
354 |
355 | options
356 |
357 | adminhtml/system_config_source_yesno
358 |
359 |
360 |
361 |
362 | is_active
363 |
364 | is_active
365 |
366 | options
367 |
368 | adminhtml/system_config_source_yesno
369 |
370 |
371 |
372 |
373 | sort_order
374 |
375 | sort_order
376 | number
377 |
378 | 50px
379 | right
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 | {{id}}
388 |
389 |
390 |
391 | id
392 |
393 |
394 | desc
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 | 1
410 |
411 |
412 | 1
413 |
414 |
415 |
416 |
417 |
418 | New Rule
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 | aoe_fraudmanager_holdrule_edit_tabs
431 |
432 |
433 | edit_form
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 | main
448 | main
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 | conditions
460 | conditions
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 | Edit Rule
471 |
472 |
473 | delete
474 |
475 |
476 |
477 | deleteConfirm('%s', '%s')
478 | Are you sure you want to do this?
479 |
480 |
481 |
482 |
483 | delete
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 | Testing Order #%s Against All Hold Rules
495 |
496 |
497 | increment_id
498 |
499 |
500 |
501 |
502 | add
503 |
504 |
505 | back
506 |
507 |
508 |
509 | setLocation('%s')
510 |
511 |
512 | back
513 |
514 |
515 |
516 |
517 | aoe_fraudmanager_holdrule_testorder_grid
518 |
519 |
520 | 0
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 | 0
529 |
530 |
531 | 0
532 |
533 |
534 | id
535 |
536 | id
537 | number
538 |
539 | 50px
540 | right
541 |
542 |
543 |
544 | name
545 |
546 |
547 | name
548 | text
549 |
550 |
551 |
552 | is_active
553 |
554 | is_active
555 |
556 | options
557 |
558 | adminhtml/system_config_source_yesno
559 |
560 |
561 |
562 |
563 | triggered
564 |
565 | triggered
566 |
567 | options
568 |
569 | adminhtml/system_config_source_yesno
570 |
571 |
572 |
573 |
574 | skipped
575 |
576 | skipped
577 |
578 | options
579 |
580 | adminhtml/system_config_source_yesno
581 |
582 |
583 |
584 |
585 | timing
586 |
587 | timing
588 | number
589 |
590 | 50px
591 | right
592 |
593 |
594 |
595 | status
596 |
597 | status
598 |
599 | options
600 |
601 | adminhtml/system_config_source_order_status
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 | {{id}}
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 | is_fraud
629 |
630 | is_fraud
631 | options
632 |
633 | 70px
634 |
635 | adminhtml/system_config_source_yesno
636 |
637 |
638 | status
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 | aoe_fraudmanager/sales/order/view/info.phtml
648 |
649 |
650 |
651 |
652 | set_fraud_flag
653 |
654 |
655 |
656 | setLocation('%s')
657 |
658 |
659 |
660 |
661 |
662 | remove_fraud_flag
663 |
664 |
665 |
666 | setLocation('%s')
667 |
668 |
669 |
670 |
671 |
672 | test_blacklist_rules
673 |
674 |
675 |
676 | setLocation('%s')
677 |
678 |
679 | go
680 |
681 | 10
682 |
683 |
684 | test_hold_rules
685 |
686 |
687 |
688 | setLocation('%s')
689 |
690 |
691 | go
692 |
693 | 10
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 | Mark Order #%s as Fraud
704 |
705 |
706 | increment_id
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 | action
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 | Mark Order #%s as NOT Fraud
728 |
729 |
730 | increment_id
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 | action
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
--------------------------------------------------------------------------------