1
0
Fork 0
mirror of synced 2025-04-05 06:03:37 +03:00

Compare commits

...

78 commits

Author SHA1 Message Date
Eugene Polozov
d7d1cc0d46 The module is marked as deprecated 2021-03-26 15:45:40 +03:00
opheugene
7b21d2c66b
Move to Github Actions 2021-01-30 15:37:57 +03:00
Eugene Polozov
b0d1b7c9fb Change version in magento composer 2020-12-23 15:59:43 +03:00
opheugene
2fb72e4fc0
Rebranding RetailCRM, fix tests 2020-12-23 15:27:23 +03:00
Eugene Polozov
f50a102cc8 Rebranding RetailCRM, fix tests 2020-12-23 10:54:39 +03:00
Akolzin Dmitry
e62591895d
update travis config (#32) 2020-05-18 16:34:25 +03:00
Evgeniy-Goroh
97a9e8b27c
Save config dinamic fields
* save config dinamic fields
* update test
2020-05-18 12:19:01 +03:00
Alex Lushpai
ae03c8c881
Remove unnecessary code
fixes #30
2020-04-16 12:04:10 +03:00
gorokh
966406a609 issues #30 removed unnecessary code 2020-04-07 18:16:09 +03:00
Alex Lushpai
c2c2fa0a95
Merge pull request #28 from Evgeniy-Goroh/master
fix test
2019-10-24 10:49:29 +03:00
gorokh
65e44090de fix test 2019-10-21 14:50:06 +03:00
Alex Lushpai
a314a47d70
Merge pull request #27 from gwinn/master
fix version & travis config
2019-10-17 15:08:23 +03:00
Alex Lushpai
cd1061dfd1 update php version for travis 2019-10-17 14:23:19 +03:00
Alex Lushpai
033817af84 fix version & travis config 2019-10-17 13:40:32 +03:00
Alex Lushpai
4e9c9c087e
Merge pull request #26 from Evgeniy-Goroh/master
Поддержка функции добавления одинакового товара в заказ как разные позиции
2019-10-17 13:36:05 +03:00
Alex Lushpai
43c3e5be80
Merge branch 'master' into master 2019-10-17 13:35:30 +03:00
Alex Lushpai
227b0eb827
Update .travis.yml 2019-10-17 13:15:24 +03:00
Alex Lushpai
56deb86d1c
Update VERSION 2019-10-17 13:11:00 +03:00
Alex Lushpai
2756b8e797
Update CHACNGELOG.md 2019-10-17 13:10:42 +03:00
Alex Lushpai
99ff83c83c
Update .travis.yml 2019-10-17 13:09:47 +03:00
gorokh
fc1e208b08 fix price 2019-10-01 14:40:42 +03:00
gorokh
06ddf9a807 Поддержка функции добавления одинакового товара в заказ как разные товарные позиции из CRM 2019-09-26 16:39:02 +03:00
Alex Lushpai
23602a7b71
Merge pull request #25 from iyzoer/master
Delete duplicate injection
2019-05-07 11:50:59 +03:00
Akolzin Dmitry
7b3b49e563 Fix test 2019-03-21 10:37:20 +03:00
Akolzin Dmitry
2ed36df9f1 Delete duplicate injection 2019-03-21 10:10:55 +03:00
Alex Lushpai
6e9629efef
Merge pull request #22 from sergeygw1990/master
v2.4.1
2019-02-14 13:23:14 +03:00
Sergey
3b97a7f06c v2.4.1 2019-02-12 15:35:53 +03:00
Alex Lushpai
fd2524b207
Merge pull request #21 from iyzoer/master
Fixes for marketplace
2019-01-24 16:11:07 +03:00
Akolzin Dmitry
ccb1a6e77d Fixes for marketplace 2019-01-24 16:01:09 +03:00
Alex Lushpai
86124b1978
Merge pull request #20 from sergeygw1990/master
v2.4.0
2019-01-24 14:33:56 +03:00
Sergey
950f00ac5c fix version change in composer.json 2019-01-24 13:40:33 +03:00
Sergey
6f47b16cbd fix Add constant inventories in src/Helper/Data.php 2019-01-24 12:34:09 +03:00
Sergey
a6d80bf154 v2.4.0 2019-01-24 11:39:40 +03:00
Alex Lushpai
b15f8ec5a8
Merge pull request #19 from iyzoer/master
Изменена логика передачи данных по заказам и клиентам
2019-01-23 13:46:36 +03:00
Akolzin Dmitry
2c8a87c582 Добавлены настройки Daemon Collector 2019-01-22 10:00:52 +03:00
Akolzin Dmitry
f4eca5a7b0 Изменена логика передачи данных по заказам и клиентам 2019-01-18 11:46:10 +03:00
Alex Lushpai
6dd54014ae
Merge pull request #18 from iyzoer/master
Выгрузка габаритов и веса в ICML
2019-01-16 10:36:27 +03:00
Akolzin Dmitry
6e66eb3aea Выгрузка габаритов и веса в ICML 2019-01-15 14:13:20 +03:00
Alex Lushpai
23bfe5c6fb
Merge pull request #17 from iyzoer/master
v2.3.2
2018-12-25 15:34:06 +03:00
Akolzin Dmitry
09090fdd5f v2.3.2 2018-12-25 15:07:54 +03:00
Alex Lushpai
5b6a9762d8
Merge pull request #16 from iyzoer/master
v2.3.1
2018-10-25 13:09:48 +03:00
Akolzin Dmitry
5ecedd12f0 Unit test update 2018-10-25 12:55:32 +03:00
Akolzin Dmitry
ef12474dfc Update changelog 2018-10-25 12:38:17 +03:00
Akolzin Dmitry
15da35916a Добавлена возможность создания нескольких модулей в маркетплейсе 2018-10-25 12:35:40 +03:00
Akolzin Dmitry
f47af54f1a Send to CRM activate/deactivate information in marketplace 2018-10-25 12:35:40 +03:00
Alex Lushpai
520ad44dce
Merge pull request #14 from iyzoer/master
Update version in composer.json
2018-08-31 12:54:14 +03:00
Akolzin Dmitry
c052dc2437 Update version in composer.json 2018-08-31 12:23:47 +03:00
Alex Lushpai
0ed0795be4
Merge pull request #13 from iyzoer/master
v2.3.0
2018-08-21 11:16:07 +03:00
Akolzin Dmitry
e93d2e2018 Update README, update tests 2018-08-21 10:47:31 +03:00
Akolzin Dmitry
cc995b83f5 v2.3.0 2018-08-21 10:19:08 +03:00
Alex Lushpai
9ef3f038c2
Update README.md 2018-06-18 14:02:20 +03:00
Alex Lushpai
2dd34395a3
Update VERSION 2018-06-14 13:19:00 +03:00
Alex Lushpai
9d402797fa
Update README.ru.md 2018-06-14 12:56:00 +03:00
Alex Lushpai
9ef2baf81d
Merge pull request #11 from iyzoer/master
Multisite, tests
2018-06-14 12:42:34 +03:00
Akolzin Dmitry
4cb74ededa
Update Makefile 2018-06-14 12:11:29 +03:00
Akolzin Dmitry
4c23faf1f4 Added script.sh, updated travis config 2018-05-15 16:44:45 +03:00
Akolzin Dmitry
7e7556fef3 Multisite, tests, travis 2018-05-15 15:54:55 +03:00
Akolzin Dmitry
6b83c72f93 Update system.xml 2018-05-11 10:04:51 +03:00
Akolzin Dmitry
364b12e6d4 Update travis.yml 2018-05-04 17:42:17 +03:00
Akolzin Dmitry
2d96fcc531 Update database name in install.sh 2018-05-04 17:14:06 +03:00
Akolzin Dmitry
5c8fa3ee01 Update magento install 2018-05-04 17:07:37 +03:00
Akolzin Dmitry
ad4b469548 Delete pass from install.sh 2018-05-04 17:03:31 +03:00
Akolzin Dmitry
0e40ad1b5f Tests, travis
Src directory
2018-05-04 16:27:45 +03:00
Akolzin Dmitry
3b6430cf7d Refactoring 2018-04-28 11:59:43 +03:00
Akolzin Dmitry
dd515492ab Readme 2018-04-28 11:59:43 +03:00
Akolzin Dmitry
682fcb8545 Multiversions api (#8) 2018-03-12 16:34:48 +03:00
Alex Lushpai
b5bb377379 Update README.md 2017-06-02 10:32:20 +03:00
Alex Lushpai
f4000c9874 v2.0 2017-05-31 15:24:46 +03:00
Alex Lushpai
f838099bb0 Merge pull request #5 from Rugento/patch-2
Update Order.php
2017-05-18 13:10:47 +03:00
Alex Lushpai
335c192a0e Merge pull request #6 from devzorg/patch-1
Support an purchase price
2017-05-18 13:09:48 +03:00
Oleg
b0402f3558 Support an purchase price
Use Cost attribute in Magento. Don't forget to select this attribute for exchange with RetailCRM for purchase price feature.
2017-05-17 16:33:29 +03:00
Rugento
02bfb8224f Update and rename Order.php to Rugento
Забыли массив
2017-05-14 23:03:15 +03:00
Alex Lushpai
8c51adafed Merge pull request #3 from Evgeniy-Goroh/master
API v4 and order history
2017-03-16 14:14:13 +03:00
Evgeniy-Goroh
834c553173 API v4 and history order 2017-02-03 11:05:00 +03:00
Alex Lushpai
7d3a1bb75e Merge pull request #2 from DmitryKorol/master
offers, customer upload on event, orders update
2016-09-08 18:08:29 +03:00
Alex Lushpai
c8217c85d3 Merge pull request #1 from gaidarzhi/master
Update README.md
2016-09-08 18:07:21 +03:00
dkorol
aeffa5ba6e offers, customer upload on event, orders update 2016-09-08 17:41:04 +03:00
gaidarzhi
366e524ad2 Update README.md 2016-09-02 16:08:25 +03:00
112 changed files with 8572 additions and 2541 deletions

234
.github/workflows/magento.yml vendored Normal file
View file

@ -0,0 +1,234 @@
# This is a basic workflow to help you get started with Actions
name: magento
on:
push:
branches:
- '**'
tags-ignore:
- '*.*'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- php-version: '7.0'
branch: '2.0.2'
coverage: 1
- php-version: '7.0'
branch: '2.0.4'
- php-version: '7.0'
branch: '2.0.5'
- php-version: '7.0'
branch: '2.0.6'
- php-version: '7.0'
branch: '2.0.7'
- php-version: '7.0'
branch: '2.0.8'
- php-version: '7.0'
branch: '2.0.9'
- php-version: '7.0'
branch: '2.0.10'
- php-version: '7.0'
branch: '2.0.11'
- php-version: '7.0'
branch: '2.0.12'
- php-version: '7.0'
branch: '2.0.13'
- php-version: '7.0'
branch: '2.0.14'
- php-version: '7.0'
branch: '2.0.15'
- php-version: '7.0'
branch: '2.0.16'
- php-version: '7.0'
branch: '2.0.17'
- php-version: '7.0'
branch: '2.0.18'
- php-version: '7.0'
branch: '2.1.0'
- php-version: '7.0'
branch: '2.1.1'
- php-version: '7.0'
branch: '2.1.2'
- php-version: '7.0'
branch: '2.1.3'
- php-version: '7.0'
branch: '2.1.4'
- php-version: '7.0'
branch: '2.1.5'
- php-version: '7.0'
branch: '2.1.6'
- php-version: '7.0'
branch: '2.1.7'
- php-version: '7.0'
branch: '2.1.8'
- php-version: '7.0'
branch: '2.1.9'
- php-version: '7.0'
branch: '2.1.10'
- php-version: '7.0'
branch: '2.1.11'
- php-version: '7.0'
branch: '2.1.12'
- php-version: '7.0'
branch: '2.1.13'
- php-version: '7.0'
branch: '2.1.14'
- php-version: '7.0'
branch: '2.1.15'
- php-version: '7.0'
branch: '2.1.16'
- php-version: '7.1'
branch: '2.1.16'
- php-version: '7.0'
branch: '2.1.17'
- php-version: '7.1'
branch: '2.1.17'
- php-version: '7.0'
branch: '2.1.18'
- php-version: '7.1'
branch: '2.1.18'
- php-version: '7.0'
branch: '2.2.0'
- php-version: '7.1'
branch: '2.2.0'
- php-version: '7.0'
branch: '2.2.1'
- php-version: '7.1'
branch: '2.2.1'
- php-version: '7.0'
branch: '2.2.2'
- php-version: '7.1'
branch: '2.2.2'
- php-version: '7.0'
branch: '2.2.3'
- php-version: '7.1'
branch: '2.2.3'
- php-version: '7.0'
branch: '2.2.4'
- php-version: '7.1'
branch: '2.2.4'
- php-version: '7.0'
branch: '2.2.5'
- php-version: '7.1'
branch: '2.2.5'
- php-version: '7.0'
branch: '2.2.6'
- php-version: '7.1'
branch: '2.2.6'
- php-version: '7.0'
branch: '2.2.7'
- php-version: '7.1'
branch: '2.2.7'
- php-version: '7.0'
branch: '2.2.8'
- php-version: '7.1'
branch: '2.2.8'
- php-version: '7.0'
branch: '2.2.9'
- php-version: '7.1'
branch: '2.2.9'
- php-version: '7.0'
branch: '2.2.10'
- php-version: '7.1'
branch: '2.2.10'
services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 3306/tcp
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
steps:
- uses: actions/checkout@v2
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: xdebug
tools: composer:v1, phpunit:6.4.3
extensions: gd, mbstring, zip, mcrypt, pdo_mysql, dom, soap, bcmath
- name: Start mysql service
run: sudo /etc/init.d/mysql start
- name: Status mysql service
run: sudo systemctl status mysql
- name: Install Magento
env:
BRANCH: ${{ matrix.branch }}
PUBLIC_KEY: ${{ secrets.PUBLIC_KEY}}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY}}
run: make before_script
- name: Run tests
run: make test
- name: Coverage
env:
COVERAGE: ${{ matrix.coverage }}
if: env.COVERAGE == 1
run: |
make coverage
bash <(curl -s https://codecov.io/bash)
deploy:
needs: ['test']
if: success() && github.event_name == 'push' && github.repository_owner == 'retailcrm' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP 7.2
uses: shivammathur/setup-php@v2
with:
php-version: '7.2'
tools: composer:v1
- name: Build release
run: |
git fetch origin --unshallow --tags
export LAST_TAG=`git describe --abbrev=0 --tags`
export VERSION=`cat VERSION`
export ARCHIVE_NAME=retailcrm-$VERSION.ocmod.zip
export ARCHIVE_PATH="/tmp/$ARCHIVE_NAME"
export RELEASE_TAG=v$VERSION
export LAST_COMMIT=`git log --oneline --format=%B -n 1 HEAD | head -n 1`
echo RELEASE_TAG=$RELEASE_TAG >> $GITHUB_ENV
echo LAST_TAG=$LAST_TAG >> $GITHUB_ENV
echo LAST_COMMIT=$LAST_COMMIT >> $GITHUB_ENV
echo ARCHIVE_PATH=$ARCHIVE_PATH >> $GITHUB_ENV
echo ARCHIVE_NAME=$ARCHIVE_NAME >> $GITHUB_ENV
make build_archive
- name: Create Release
id: create_release
uses: actions/create-release@v1
if: env.LAST_TAG != env.RELEASE_TAG
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
with:
tag_name: ${{ env.RELEASE_TAG }}
release_name: ${{ env.RELEASE_TAG }}
body: ${{ env.LAST_COMMIT }}
draft: false
prerelease: false
- name: Cleanup
if: env.LAST_TAG != env.RELEASE_TAG
run: make delete_archive

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/nbproject/private/
.idea

30
CHANGELOG.md Normal file
View file

@ -0,0 +1,30 @@
## 2021-01-30 v.2.5.2
* Переход на GitHub Actions
## 2020-12-17 v.2.5.1
* Ребрендинг RetailCRM
## 2018-12-25 v.2.5.0
* Поддержка передачи в заказе нескольких позиций одного товара
## 2018-12-25 v.2.4.1
* Удалена генерация externalId покупателя при заказе от незарегестрированного пользователя
## 2018-12-25 v.2.4.0
* Добавлен функционал получения остатков из RetailCRM
## 2018-12-25 v.2.3.2
* Добавлена выгрузка картинок категорий товаров в ICML
## 2018-10-25 v.2.3.1
* Добавлена активация модуля в маркетплейсе RetailCRM
## 2018-08-21 v.2.3.0
* Добавлены консольные команды для выгрузки архива клиентов и заказов
* Обработка данных для формирования структуры перед отправкой вынесена в сервисы
* Теперь при ручной выгрузке заказов из админки не нужно сохранять номера заказов
* ICML каталог теперь формируется для каждого сайта
* При формировании каталога выгружаются выбранные атрибуты товаров
* Улучшена выгрузка товаров в заказе (теперь учитываются конфигурируемые товары)
* Добавлены переводы на русский и испанский языки
* Из обработки истории удален менеджер объектов

24
Makefile Normal file
View file

@ -0,0 +1,24 @@
export ROOT_DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
VERSION = `cat $(FILE)`
ARCHIVE_NAME = '/tmp/retailcrm-retailcrm-'$(VERSION)'.zip'
MAGE_ROOT=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/../magento2
.PHONY: build_archive delete_archive
build_archive:
cd src; zip -r $(ARCHIVE_NAME) ./*
delete_archive:
rm -f $(ARCHIVE_NAME)
test:
mkdir coverage
php $(MAGE_ROOT)/vendor/phpunit/phpunit/phpunit -c $(MAGE_ROOT)/dev/tests/unit/phpunit.xml.dist $(MAGE_ROOT)/app/code/Retailcrm/Retailcrm/Test/Unit
before_script:
bash bin/install.sh
coverage:
wget https://phar.phpunit.de/phpcov-2.0.2.phar && php phpcov-2.0.2.phar merge coverage/ --clover coverage.xml

View file

@ -1,11 +1,36 @@
Magento module
[![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/)
[![Build Status](https://github.com/retailcrm/magento-module/workflows/magento/badge.svg)](https://github.com/retailcrm/magento-module/actions)
[![Coverage](https://img.shields.io/codecov/c/gh/retailcrm/magento-module/master.svg?logo=github)](https://codecov.io/gh/retailcrm/magento-module)
[![GitHub release](https://img.shields.io/github/release/retailcrm/magento-module.svg?logo=codecov)](https://github.com/retailcrm/magento-module/)
[![PHP version](https://img.shields.io/badge/PHP->=5.6-blue.svg?style=flat-square)](https://php.net/)
DEPRECATED Magento module
==============
Magento module for interaction with [RetailCRM](http://www.retailcrm.ru) through [REST API](http://retailcrm.ru/docs/Разработчики).
**The module is deprecated and no longer supported**
Magento 2 module for interaction with [RetailCRM](http://www.retailcrm.ru) ([Documentation](https://docs.retailcrm.pro/Users/Integration/SiteModules/Magento) page)
Module allows:
* Exchange the orders with retailCRM
* Configure relations between dictionaries of RetailCRM and Magento (statuses, payments, delivery types and etc)
* Generate [ICML](http://docs.retailcrm.ru/index.php?n=Разработчики.ФорматICML) (Intaro Markup Language) for catalog loading by RetailCRM
* Exchange the orders data with RetailCRM
* Configure relations between dictionaries of retailCRM and Magento (statuses, payments, delivery types and etc)
* Generate [ICML](http://www.retailcrm.ru/docs/Developers/ICML) (Intaro Markup Language) export file for catalog loading by RetailCRM
## ICML
By default ICML file is being generated by module every 4 hours. You can find file in the web root folder with name "retailcrm_{{shop_code}}.xml". For example, http://example.org/retailcrm_default.xml
### Manual install
1) Run into your project root directory:
1) Unpack the archive with the module in the directory "app/code/Retailcrm/Retailcrm". In the file "app/etc/config.php" in array `modules` add an element `'Retailcrm_Retailcrm' => 1`
2) Run into your project directory:
```bash
composer require retailcrm/api-client-php ~5.0
```
This module is compatible with Magento up to version 2.2.8

30
README.ru.md Normal file
View file

@ -0,0 +1,30 @@
DEPRECATED Magento module
**Модуль устарел и больше не поддерживается**
Модуль Magento 2 для интеграции с [RetailCRM](http://www.retailcrm.ru) ([Документация](https://docs.retailcrm.ru/Users/Integration/SiteModules/Magento))
Модуль позволяет:
* Производить обмен заказами с RetailCRM
* Настроить соответствие справочников RetailCRM и Magento (статусы, оплаты, типы доставки и т.д.)
* Создать [ICML](http://www.retailcrm.ru/docs/Developers/ICML) (Intaro Markup Language) для загрузки каталога товаров в RetailCRM
## ICML
По умолчанию ICML-файл генерируется модулем каждые 4 часа. Вы можете найти файл в корневой папке с именем «retailcrm_{{shop_code}}.xml". Например, http://example.ru/retailcrm_default.xml
## Ручная установка
1) Распакуйте архив с модулем в директорию "app/code/Retailcrm/Retailcrm". В файле "app/etc/config.php" в массив `modules` добавьте элемент `'Retailcrm_Retailcrm' => 1`
2) Выполните в папке проекта:
```bash
composer require retailcrm/api-client-php ~5.0
```
В конфигурационный файл `composer.json` вашего проекта будет добавлена библиотека [retailcrm/api-client-php](https://github.com/retailcrm/api-client-php), которая будет установлена в директорию `vendor/`.
Этот модуль совместим с Magento 2 до версии 2.2.8

1
VERSION Normal file
View file

@ -0,0 +1 @@
2.5.2

View file

@ -1,36 +0,0 @@
<?php
class Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Base extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
{
protected $_fieldRenderer;
protected $_values;
protected $_apiKey;
protected $_apiUrl;
protected $_isCredentialCorrect;
public function __construct()
{
parent::__construct();
$this->_apiUrl = Mage::getStoreConfig('retailcrm/general/api_url');
$this->_apiKey = Mage::getStoreConfig('retailcrm/general/api_key');
$this->_isCredentialCorrect = false;
if (!empty($this->_apiUrl) && !empty($this->_apiKey)) {
$client = Mage::getModel(
'retailcrm/ApiClient',
array('url' => $this->_apiUrl, 'key' => $this->_apiKey, 'site' => null)
);
try {
$response = $client->sitesList();
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
if ($response->isSuccessful()) {
$this->_isCredentialCorrect = true;
}
}
}
}

View file

@ -1,87 +0,0 @@
<?php
class Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Payment extends Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Base
{
public function render(Varien_Data_Form_Element_Abstract $element)
{
$html = $this->_getHeaderHtml($element);
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$groups = Mage::getSingleton('payment/config')->getActiveMethods();
foreach ($groups as $group) {
$html .= $this->_getFieldHtml($element, $group);
}
} else {
$html .= '<div style="margin-left: 15px;"><b><i>Please check your API Url & API Key</i></b></div>';
}
$html .= $this->_getFooterHtml($element);
return $html;
}
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
}
return $this->_fieldRenderer;
}
/**
* @return array
*/
protected function _getValues()
{
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$client = Mage::getModel(
'retailcrm/ApiClient',
array('url' => $this->_apiUrl, 'key' => $this->_apiKey, 'site' => null)
);
try {
$paymentTypes = $client->paymentTypesList();
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
if ($paymentTypes->isSuccessful()) {
if (empty($this->_values)) {
foreach ($paymentTypes['paymentTypes'] as $type) {
$this->_values[] = array('label' => Mage::helper('adminhtml')->__($type['name']), 'value' => $type['code']);
}
}
}
}
return $this->_values;
}
protected function _getFieldHtml($fieldset, $group)
{
$configData = $this->getConfigData();
$path = 'retailcrm/payment/' . $group->getId();
if (isset($configData[$path])) {
$data = $configData[$path];
$inherit = false;
} else {
$data = (int)(string)$this->getForm()->getConfigRoot()->descend($path);
$inherit = true;
}
$field = $fieldset->addField('payment_' . $group->getId(), 'select',
array(
'name' => 'groups[payment][fields]['.$group->getId().'][value]',
'label' => Mage::getStoreConfig('payment/'.$group->getId().'/title'),
'value' => $data,
'values' => $this->_getValues(),
'inherit' => $inherit,
'can_use_default_value' => 1,
'can_use_website_value' => 1
))->setRenderer($this->_getFieldRenderer());
return $field->toHtml();
}
}

View file

@ -1,88 +0,0 @@
<?php
class Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Shipping extends Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Base
{
public function render(Varien_Data_Form_Element_Abstract $element)
{
$html = $this->_getHeaderHtml($element);
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$groups = Mage::getSingleton('shipping/config')->getActiveCarriers();
foreach ($groups as $group) {
$html .= $this->_getFieldHtml($element, $group);
}
} else {
$html .= '<div style="margin-left: 15px;"><b><i>Please check your API Url & API Key</i></b></div>';
}
$html .= $this->_getFooterHtml($element);
return $html;
}
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
}
return $this->_fieldRenderer;
}
/**
* @return array
*/
protected function _getValues()
{
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$client = Mage::getModel(
'retailcrm/ApiClient',
array('url' => $this->_apiUrl, 'key' => $this->_apiKey, 'site' => null)
);
try {
$deliveryTypes = $client->deliveryTypesList();
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
if ($deliveryTypes->isSuccessful()) {
if (empty($this->_values)) {
foreach ($deliveryTypes['deliveryTypes'] as $type) {
$this->_values[] = array('label'=>Mage::helper('adminhtml')->__($type['name']), 'value'=>$type['code']);
}
}
}
}
return $this->_values;
}
protected function _getFieldHtml($fieldset, $group)
{
$configData = $this->getConfigData();
$path = 'retailcrm/shipping/' . $group->getId();
if (isset($configData[$path])) {
$data = $configData[$path];
$inherit = false;
} else {
$data = (int)(string)$this->getForm()->getConfigRoot()->descend($path);
$inherit = true;
}
$field = $fieldset->addField('shipping_' . $group->getId(), 'select',
array(
'name' => 'groups[shipping][fields]['.$group->getId().'][value]',
'label' => Mage::getStoreConfig('carriers/'.$group->getId().'/title'),
'value' => $data,
'values' => $this->_getValues(),
'inherit' => $inherit,
'can_use_default_value' => 1,
'can_use_website_value' => 1
))->setRenderer($this->_getFieldRenderer());
return $field->toHtml();
}
}

View file

@ -1,89 +0,0 @@
<?php
class Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Status extends Retailcrm_Retailcrm_Block_Adminhtml_System_Config_Form_Fieldset_Base
{
public function render(Varien_Data_Form_Element_Abstract $element)
{
$html = $this->_getHeaderHtml($element);
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$statuses = Mage::getModel('sales/order_status')->getResourceCollection()->getData();
foreach ($statuses as $status) {
$html .= $this->_getFieldHtml($element, $status);
}
} else {
$html .= '<div style="margin-left: 15px;"><b><i>Please check your API Url & API Key</i></b></div>';
}
$html .= $this->_getFooterHtml($element);
return $html;
}
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
}
return $this->_fieldRenderer;
}
/**
* @return array
*/
protected function _getValues()
{
if(!empty($this->_apiUrl) && !empty($this->_apiKey) && $this->_isCredentialCorrect) {
$client = Mage::getModel(
'retailcrm/ApiClient',
array('url' => $this->_apiUrl, 'key' => $this->_apiKey, 'site' => null)
);
try {
$statuses = $client->statusesList();
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
if ($statuses->isSuccessful()) {
if (empty($this->_values)) {
foreach ($statuses['statuses'] as $status) {
$this->_values[] = array('label'=>Mage::helper('adminhtml')->__($status['name']), 'value'=>$status['code']);
}
}
}
}
return $this->_values;
}
protected function _getFieldHtml($fieldset, $group)
{
$configData = $this->getConfigData();
$path = 'retailcrm/status/' . $group['status'];
if (isset($configData[$path])) {
$data = $configData[$path];
$inherit = false;
} else {
$data = (int)(string)$this->getForm()->getConfigRoot()->descend($path);
$inherit = true;
}
$field = $fieldset->addField('status_' . $group['status'], 'select',
array(
'name' => 'groups[status][fields]['.$group['status'].'][value]',
'label' => $group['label'],
'value' => $data,
'values' => $this->_getValues(),
'inherit' => $inherit,
'can_use_default_value' => 1,
'can_use_website_value' => 1
))->setRenderer($this->_getFieldRenderer());
return $field->toHtml();
}
}

View file

@ -1,58 +0,0 @@
<?php
/**
* Data helper
*
* @author RetailCRM
*/
class Retailcrm_Retailcrm_Helper_Data extends Mage_Core_Helper_Abstract
{
/**
* Path to store config if front-end output is enabled
*
* @var string
*/
const XML_API_URL = 'retailcrm/general/api_url';
/**
* Path to store config where count of news posts per page is stored
*
* @var string
*/
const XML_API_KEY = 'retailcrm/general/api_key';
/**
* Return api url
*
* @param integer|string|Mage_Core_Model_Store $store
* @return int
*/
public function getApiUrl($store = null)
{
return abs((int)Mage::getStoreConfig(self::XML_API_URL, $store));
}
/**
* Return api key
*
* @param integer|string|Mage_Core_Model_Store $store
* @return int
*/
public function getApiKey($store = null)
{
return abs((int)Mage::getStoreConfig(self::XML_API_KEY, $store));
}
public function rewrittenProductUrl($productId, $categoryId, $storeId)
{
$coreUrl = Mage::getModel('core/url_rewrite');
$idPath = sprintf('product/%d', $productId);
if ($categoryId) {
$idPath = sprintf('%s/%d', $idPath, $categoryId);
}
$coreUrl->setStoreId($storeId);
$coreUrl->loadByIdPath($idPath);
return Mage::getBaseUrl( Mage_Core_Model_Store::URL_TYPE_WEB, true ) . $coreUrl->getRequestPath();
}
}

View file

@ -1,813 +0,0 @@
<?php
/**
* retailCRM API client class
*/
class Retailcrm_Retailcrm_Model_ApiClient
{
const VERSION = 'v3';
protected $client;
/**
* Site code
*/
protected $siteCode;
/**
* Retailcrm_Retailcrm_Model_Http_Client init
*
* @param string $url
* @param string $apiKey
* @param string $siteCode
* @return mixed
*/
public function __construct($params)
{
$url = $params['url'];
if ('/' != substr($url, strlen($url) - 1, 1)) {
$url .= '/';
}
$url = $url . 'api/' . self::VERSION;
$this->client = new Retailcrm_Retailcrm_Model_Http_Client($url, array('apiKey' => $params['key']));
$this->siteCode = $params['site'];
}
/**
* Create a order
*
* @param array $order
* @param string $site (default: null)
* @return ApiResponse
*/
public function ordersCreate(array $order, $site = null)
{
if (!sizeof($order)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `order` must contains a data');
}
return $this->client->makeRequest("/orders/create", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, $this->fillSite($site, array(
'order' => json_encode($order)
)));
}
/**
* Edit a order
*
* @param array $order
* @param string $site (default: null)
* @return ApiResponse
*/
public function ordersEdit(array $order, $by = 'externalId', $site = null)
{
if (!sizeof($order)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `order` must contains a data');
}
$this->checkIdParameter($by);
if (!isset($order[$by])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException(sprintf('Order array must contain the "%s" parameter.', $by));
}
return $this->client->makeRequest(
"/orders/" . $order[$by] . "/edit",
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
$this->fillSite($site, array(
'order' => json_encode($order),
'by' => $by,
))
);
}
/**
* Upload array of the orders
*
* @param array $orders
* @param string $site (default: null)
* @return ApiResponse
*/
public function ordersUpload(array $orders, $site = null)
{
if (!sizeof($orders)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `orders` must contains array of the orders');
}
return $this->client->makeRequest("/orders/upload", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, $this->fillSite($site, array(
'orders' => json_encode($orders),
)));
}
/**
* Get order by id or externalId
*
* @param string $id
* @param string $by (default: 'externalId')
* @param string $site (default: null)
* @return ApiResponse
*/
public function ordersGet($id, $by = 'externalId', $site = null)
{
$this->checkIdParameter($by);
return $this->client->makeRequest("/orders/$id", Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $this->fillSite($site, array(
'by' => $by
)));
}
/**
* Returns a orders history
*
* @param DateTime $startDate (default: null)
* @param DateTime $endDate (default: null)
* @param int $limit (default: 100)
* @param int $offset (default: 0)
* @param bool $skipMyChanges (default: true)
* @return ApiResponse
*/
public function ordersHistory(
DateTime $startDate = null,
DateTime $endDate = null,
$limit = 100,
$offset = 0,
$skipMyChanges = true
) {
$parameters = array();
if ($startDate) {
$parameters['startDate'] = $startDate->format('Y-m-d H:i:s');
}
if ($endDate) {
$parameters['endDate'] = $endDate->format('Y-m-d H:i:s');
}
if ($limit) {
$parameters['limit'] = (int) $limit;
}
if ($offset) {
$parameters['offset'] = (int) $offset;
}
if ($skipMyChanges) {
$parameters['skipMyChanges'] = (bool) $skipMyChanges;
}
return $this->client->makeRequest('/orders/history', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $parameters);
}
/**
* Returns filtered orders list
*
* @param array $filter (default: array())
* @param int $page (default: null)
* @param int $limit (default: null)
* @return ApiResponse
*/
public function ordersList(array $filter = array(), $page = null, $limit = null)
{
$parameters = array();
if (sizeof($filter)) {
$parameters['filter'] = $filter;
}
if (null !== $page) {
$parameters['page'] = (int) $page;
}
if (null !== $limit) {
$parameters['limit'] = (int) $limit;
}
return $this->client->makeRequest('/orders', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $parameters);
}
/**
* Returns statuses of the orders
*
* @param array $ids (default: array())
* @param array $externalIds (default: array())
* @return ApiResponse
*/
public function ordersStatuses(array $ids = array(), array $externalIds = array())
{
$parameters = array();
if (sizeof($ids)) {
$parameters['ids'] = $ids;
}
if (sizeof($externalIds)) {
$parameters['externalIds'] = $externalIds;
}
return $this->client->makeRequest('/orders/statuses', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $parameters);
}
/**
* Save order IDs' (id and externalId) association in the CRM
*
* @param array $ids
* @return ApiResponse
*/
public function ordersFixExternalIds(array $ids)
{
if (!sizeof($ids)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Method parameter must contains at least one IDs pair');
}
return $this->client->makeRequest("/orders/fix-external-ids", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, array(
'orders' => json_encode($ids),
));
}
/**
* Get orders assembly history
*
* @param array $filter (default: array())
* @param int $page (default: null)
* @param int $limit (default: null)
* @return ApiResponse
*/
public function ordersPacksHistory(array $filter = array(), $page = null, $limit = null)
{
$parameters = array();
if (sizeof($filter)) {
$parameters['filter'] = $filter;
}
if (null !== $page) {
$parameters['page'] = (int) $page;
}
if (null !== $limit) {
$parameters['limit'] = (int) $limit;
}
return $this->client->makeRequest('/orders/packs/history', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $parameters);
}
/**
* Create a customer
*
* @param array $customer
* @param string $site (default: null)
* @return ApiResponse
*/
public function customersCreate(array $customer, $site = null)
{
if (!sizeof($customer)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `customer` must contains a data');
}
return $this->client->makeRequest("/customers/create", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, $this->fillSite($site, array(
'customer' => json_encode($customer)
)));
}
/**
* Edit a customer
*
* @param array $customer
* @param string $by (default: 'externalId')
* @param string $site (default: null)
* @return ApiResponse
*/
public function customersEdit(array $customer, $by = 'externalId', $site = null)
{
if (!sizeof($customer)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `customer` must contains a data');
}
$this->checkIdParameter($by);
if (!isset($customer[$by])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException(sprintf('Customer array must contain the "%s" parameter.', $by));
}
return $this->client->makeRequest(
"/customers/" . $customer[$by] . "/edit",
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
$this->fillSite(
$site,
array(
'customer' => json_encode($customer),
'by' => $by
)
)
);
}
/**
* Upload array of the customers
*
* @param array $customers
* @param string $site (default: null)
* @return ApiResponse
*/
public function customersUpload(array $customers, $site = null)
{
if (!sizeof($customers)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `customers` must contains array of the customers');
}
return $this->client->makeRequest("/customers/upload", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, $this->fillSite($site, array(
'customers' => json_encode($customers),
)));
}
/**
* Get customer by id or externalId
*
* @param string $id
* @param string $by (default: 'externalId')
* @param string $site (default: null)
* @return ApiResponse
*/
public function customersGet($id, $by = 'externalId', $site = null)
{
$this->checkIdParameter($by);
return $this->client->makeRequest("/customers/$id", Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $this->fillSite($site, array(
'by' => $by
)));
}
/**
* Returns filtered customers list
*
* @param array $filter (default: array())
* @param int $page (default: null)
* @param int $limit (default: null)
* @return ApiResponse
*/
public function customersList(array $filter = array(), $page = null, $limit = null)
{
$parameters = array();
if (sizeof($filter)) {
$parameters['filter'] = $filter;
}
if (null !== $page) {
$parameters['page'] = (int) $page;
}
if (null !== $limit) {
$parameters['limit'] = (int) $limit;
}
return $this->client->makeRequest('/customers', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $parameters);
}
/**
* Save customer IDs' (id and externalId) association in the CRM
*
* @param array $ids
* @return ApiResponse
*/
public function customersFixExternalIds(array $ids)
{
if (!sizeof($ids)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Method parameter must contains at least one IDs pair');
}
return $this->client->makeRequest("/customers/fix-external-ids", Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST, array(
'customers' => json_encode($ids),
));
}
/**
* Get purchace prices & stock balance
*
* @param array $filter (default: array())
* @param int $page (default: null)
* @param int $limit (default: null)
* @param string $site (default: null)
* @return ApiResponse
*/
public function storeInventories(array $filter = array(), $page = null, $limit = null, $site = null)
{
$parameters = array();
if (sizeof($filter)) {
$parameters['filter'] = $filter;
}
if (null !== $page) {
$parameters['page'] = (int) $page;
}
if (null !== $limit) {
$parameters['limit'] = (int) $limit;
}
return $this->client->makeRequest('/store/inventories', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET, $this->fillSite($site, $parameters));
}
/**
* Upload store inventories
*
* @param array $offers
* @param string $site (default: null)
* @return ApiResponse
*/
public function storeInventoriesUpload(array $offers, $site = null)
{
if (!sizeof($offers)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Parameter `offers` must contains array of the customers');
}
return $this->client->makeRequest(
"/store/inventories/upload",
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
$this->fillSite($site, array('offers' => json_encode($offers)))
);
}
/**
* Returns deliveryServices list
*
* @return ApiResponse
*/
public function deliveryServicesList()
{
return $this->client->makeRequest('/reference/delivery-services', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns deliveryTypes list
*
* @return ApiResponse
*/
public function deliveryTypesList()
{
return $this->client->makeRequest('/reference/delivery-types', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns orderMethods list
*
* @return ApiResponse
*/
public function orderMethodsList()
{
return $this->client->makeRequest('/reference/order-methods', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns orderTypes list
*
* @return ApiResponse
*/
public function orderTypesList()
{
return $this->client->makeRequest('/reference/order-types', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns paymentStatuses list
*
* @return ApiResponse
*/
public function paymentStatusesList()
{
return $this->client->makeRequest('/reference/payment-statuses', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns paymentTypes list
*
* @return ApiResponse
*/
public function paymentTypesList()
{
return $this->client->makeRequest('/reference/payment-types', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns productStatuses list
*
* @return ApiResponse
*/
public function productStatusesList()
{
return $this->client->makeRequest('/reference/product-statuses', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns statusGroups list
*
* @return ApiResponse
*/
public function statusGroupsList()
{
return $this->client->makeRequest('/reference/status-groups', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns statuses list
*
* @return ApiResponse
*/
public function statusesList()
{
return $this->client->makeRequest('/reference/statuses', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns sites list
*
* @return ApiResponse
*/
public function sitesList()
{
return $this->client->makeRequest('/reference/sites', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Returns stores list
*
* @return ApiResponse
*/
public function storesList()
{
return $this->client->makeRequest('/reference/stores', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Edit deliveryService
*
* @param array $data delivery service data
* @return ApiResponse
*/
public function deliveryServicesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/delivery-services/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'deliveryService' => json_encode($data)
)
);
}
/**
* Edit deliveryType
*
* @param array $data delivery type data
* @return ApiResponse
*/
public function deliveryTypesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/delivery-types/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'deliveryType' => json_encode($data)
)
);
}
/**
* Edit orderMethod
*
* @param array $data order method data
* @return ApiResponse
*/
public function orderMethodsEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/order-methods/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'orderMethod' => json_encode($data)
)
);
}
/**
* Edit orderType
*
* @param array $data order type data
* @return ApiResponse
*/
public function orderTypesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/order-types/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'orderType' => json_encode($data)
)
);
}
/**
* Edit paymentStatus
*
* @param array $data payment status data
* @return ApiResponse
*/
public function paymentStatusesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/payment-statuses/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'paymentStatus' => json_encode($data)
)
);
}
/**
* Edit paymentType
*
* @param array $data payment type data
* @return ApiResponse
*/
public function paymentTypesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/payment-types/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'paymentType' => json_encode($data)
)
);
}
/**
* Edit productStatus
*
* @param array $data product status data
* @return ApiResponse
*/
public function productStatusesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/product-statuses/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'productStatus' => json_encode($data)
)
);
}
/**
* Edit order status
*
* @param array $data status data
* @return ApiResponse
*/
public function statusesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/statuses/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'status' => json_encode($data)
)
);
}
/**
* Edit site
*
* @param array $data site data
* @return ApiResponse
*/
public function sitesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
return $this->client->makeRequest(
'/reference/sites/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'site' => json_encode($data)
)
);
}
/**
* Edit store
*
* @param array $data site data
* @return ApiResponse
*/
public function storesEdit(array $data)
{
if (!isset($data['code'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "code" parameter.');
}
if (!isset($data['name'])) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('Data must contain "name" parameter.');
}
return $this->client->makeRequest(
'/reference/stores/' . $data['code'] . '/edit',
Retailcrm_Retailcrm_Model_Http_Client::METHOD_POST,
array(
'store' => json_encode($data)
)
);
}
/**
* Update CRM basic statistic
*
* @return ApiResponse
*/
public function statisticUpdate()
{
return $this->client->makeRequest('/statistic/update', Retailcrm_Retailcrm_Model_Http_Client::METHOD_GET);
}
/**
* Return current site
*
* @return string
*/
public function getSite()
{
return $this->siteCode;
}
/**
* Set site
*
* @param string $site
* @return void
*/
public function setSite($site)
{
$this->siteCode = $site;
}
/**
* Check ID parameter
*
* @param string $by
* @return bool
*/
protected function checkIdParameter($by)
{
$allowedForBy = array('externalId', 'id');
if (!in_array($by, $allowedForBy)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException(sprintf(
'Value "%s" for parameter "by" is not valid. Allowed values are %s.',
$by,
implode(', ', $allowedForBy)
));
}
return true;
}
/**
* Fill params by site value
*
* @param string $site
* @param array $params
* @return array
*/
protected function fillSite($site, array $params)
{
if ($site) {
$params['site'] = $site;
} elseif ($this->siteCode) {
$params['site'] = $this->siteCode;
}
return $params;
}
}

View file

@ -1,5 +0,0 @@
<?php
class Retailcrm_Retailcrm_Model_Exception_CurlException extends RuntimeException
{
}

View file

@ -1,5 +0,0 @@
<?php
class Retailcrm_Retailcrm_Model_Exception_InvalidJsonException extends DomainException
{
}

View file

@ -1,641 +0,0 @@
<?php
class Retailcrm_Retailcrm_Model_Exchange
{
protected $_apiKey;
protected $_apiUrl;
protected $_config;
protected $_api;
public function __construct()
{
$this->_apiUrl = Mage::getStoreConfig('retailcrm/general/api_url');
$this->_apiKey = Mage::getStoreConfig('retailcrm/general/api_key');
if(!empty($this->_apiUrl) && !empty($this->_apiKey)) {
$this->_api = Mage::getModel(
'retailcrm/ApiClient',
array('url' => $this->_apiUrl, 'key' => $this->_apiKey, 'site' => null)
);
}
}
/**
* @param mixed $order
*
* @return bool
*/
public function ordersCreate($order)
{
$this->_config = Mage::getStoreConfig('retailcrm', $order->getStoreId());
$statuses = array_flip(array_filter($this->_config['status']));
$payments = array_filter($this->_config['payment']);
$shippings = array_filter($this->_config['shipping']);
$shipment = $order->getShippingMethod();
$shipment = explode('_', $shipment);
$shipment = $shipment[0];
$address = $order->getShippingAddress()->getData();
$orderItems = $order->getAllItems();
$simpleItems = array();
$confItems = array();
foreach ($orderItems as $item) {
if ($item->getProductType() == 'simple') {
$simpleItems[] = $item;
} else {
$confItems[$item->getData('item_id')] = $item;
}
}
$items = array();
foreach ($simpleItems as $item) {
$product = array(
'productId' => $item->product_id,
'productName' => $item->getName(),
'quantity' => (int) $item->getData('qty_ordered')
);
if ($item->getData('parent_item_id')) {
$product['initialPrice'] = $confItems[$item->getData('parent_item_id')]->getPrice();
/*if ($confItems[$item->getData('parent_item_id')]->getDiscountAmount() > 0) {
$product['discount'] = $confItems[$item->getData('parent_item_id')]->getDiscountAmount();
}
if ($confItems[$item->getData('parent_item_id')]->getDiscountPercent() > 0) {
$product['discountPercent'] = $confItems[$item->getData('parent_item_id')]->getDiscountPercent();
}*/
} else {
$product['initialPrice'] = $item->getPrice();
/*if ($item->getDiscountAmount() > 0) {
$product['discount'] = $item->getDiscountAmount();
}
if ($item->getDiscountPercent() > 0) {
$product['discountPercent'] = $item->getDiscountPercent();
}*/
}
$items[] = $product;
}
$customer = array(
'externalId' => ($order->getCustomerIsGuest() == 0) ? $order->getCustomerId() : 'g' . $order->getRealOrderId(),
'email' => $order->getCustomerEmail(),
'phone' => $address['telephone'],
'name' => $order->getCustomerName(),
'lastName' => $order->getCustomerLastname(),
'firstName' => $order->getCustomerFirstname(),
'patronymic' => $order->getCustomerMiddlename(),
);
$customerId = $this->setCustomerId($customer);
unset($customer);
$comment = $order->getStatusHistoryCollection()->getFirstItem();
$preparedOrder = array(
'site' => $order->getStore()->getCode(),
'externalId' => $order->getId(),
'number' => $order->getRealOrderId(),
'createdAt' => $order->getCreatedAt(),
'customerId' => $customerId,
'lastName' => $order->getCustomerLastname(),
'firstName' => $order->getCustomerFirstname(),
'patronymic' => $order->getCustomerMiddlename(),
'email' => $order->getCustomerEmail(),
'phone' => $address['telephone'],
'paymentType' => $payments[$order->getPayment()->getMethodInstance()->getCode()],
'status' => $statuses[$order->getStatus()],
'discount' => abs($order->getDiscountAmount()),
'items' => $items,
'customerComment' => $comment->getComment(),
'delivery' => array(
'code' => $shippings[$shipment],
'cost' => $order->getShippingAmount(),
'address' => array(
'index' => $address['postcode'],
'city' => $address['city'],
'country' => $address['country_id'],
'street' => $address['street'],
'region' => $address['region'],
'text' => implode(
',',
array(
$address['postcode'],
$address['country_id'],
$address['city'],
$address['street']
)
)
),
)
);
try {
$response = $this->_api->ordersCreate($preparedOrder);
if ($response->isSuccessful() && 201 === $response->getStatusCode()) {
Mage::log($response->id);
} else {
Mage::log(
sprintf(
"Order create error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
}
/**
* Get orders history & modify orders into shop
*
*/
public function ordersHistory()
{
$runTime = $this->getExchangeTime($this->_config['general']['history']);
try {
$response = $this->_api->ordersHistory($runTime);
if (
$response->isSuccessful()
&&
200 === $response->getStatusCode()
) {
$nowTime = $response->getGeneratedAt();
$this->processOrders($response->orders, $nowTime);
} else {
Mage::log(
sprintf(
"Orders history error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
}
/**
* @param array $orders
*/
private function processOrders($orders, $time)
{
if(!empty($orders)) {
Mage::getModel('core/config')->saveConfig(
'retailcrm/general/history', $time
);
foreach ($orders as $order) {
if(!empty($order['externalId'])) {
$this->doUpdate($order);
} else {
$this->doCreate($order);
}
}
die();
}
}
/**
* @param array $order
*/
private function doCreate($order)
{
try {
$response = $this->_api->ordersGet($order['id'], $by = 'id');
if (
$response->isSuccessful()
&&
200 === $response->getStatusCode()
) {
$order = $response->order;
} else {
Mage::log(
sprintf(
"Orders get error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
// get references
$this->_config = Mage::getStoreConfig('retailcrm');
$payments = array_flip(array_filter($this->_config['payment']));
$shippings = array_flip(array_filter($this->_config['shipping']));
// get store
$_store = Mage::getModel("core/store")->load($order['site']);
$_siteId = Mage::getModel('core/store')->load($_store->getId())->getWebsiteId();
$_sendConfirmation = '0';
// search or create customer
$customer = Mage::getSingleton('customer/customer');
$customer->setWebsiteId($_siteId);
$customer->loadByEmail($order['email']);
if (!is_numeric($customer->getId())) {
$customer
->setGropuId(1)
->setWebsiteId($_siteId)
->setStore($_store)
->setEmail($order['email'])
->setFirstname($order['firstName'])
->setLastname($order['lastName'])
->setMiddleName($order['patronymic'])
->setPassword(uniqid())
;
try {
$customer->save();
$customer->setConfirmation(null);
$customer->save();
} catch (Exception $e) {
Mage::log($e->getMessage());
}
$address = Mage::getModel("customer/address");
$address->setCustomerId($customer->getId())
->setFirstname($customer->getFirstname())
->setMiddleName($customer->getMiddlename())
->setLastname($customer->getLastname())
->setCountryId($this->getCountryCode($order['customer']['address']['country']))
->setPostcode($order['delivery']['address']['index'])
->setCity($order['delivery']['address']['city'])
->setTelephone($order['phone'])
->setStreet($order['delivery']['address']['street'])
->setIsDefaultBilling('1')
->setIsDefaultShipping('1')
->setSaveInAddressBook('1');
try{
$address->save();
}
catch (Exception $e) {
Mage::log($e->getMessage());
}
try {
$response = $this->_api->customersFixExternalIds(
array(
'id' => $order['customer']['id'],
'externalId' => $customer->getId()
)
);
if (
!$response->isSuccessful()
||
200 !== $response->getStatusCode()
) {
Mage::log(
sprintf(
"Orders fix error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
}
$products = array();
foreach ($order['items'] as $item) {
$products[$item['offer']['externalId']] = array('qty' => $item['quantity']);
}
$orderData = array(
'session' => array(
'customer_id' => $customer->getId(),
'store_id' => $_store->getId(),
),
'payment' => array(
'method' => $payments[$order['paymentType']],
),
'add_products' => $products,
'order' => array(
'account' => array(
'group_id' => $customer->getGroupId(),
'email' => $order['email']
),
'billing_address' => array(
'firstname' => $order['firstName'],
'middlename' => $order['patronymic'],
'lastname' => $order['lastName'],
'street' => $order['customer']['address']['street'],
'city' => $order['customer']['address']['city'],
'country_id' => $this->getCountryCode($order['customer']['address']['country']),
'region' => $order['customer']['address']['region'],
'postcode' => $order['customer']['address']['index'],
'telephone' => $order['phone'],
),
'shipping_address' => array(
'firstname' => $order['firstName'],
'middlename' => $order['patronymic'],
'lastname' => $order['lastName'],
'street' => $order['delivery']['address']['street'],
'city' => $order['delivery']['address']['city'],
'country_id' => $this->getCountryCode($order['customer']['address']['country']),
'region' => $order['delivery']['address']['region'],
'postcode' => $order['delivery']['address']['index'],
'telephone' => $order['phone'],
),
'shipping_method' => $shippings[$order['delivery']['code']],
'comment' => array(
'customer_note' => $order['customerComment'],
),
'send_confirmation' => $_sendConfirmation
)
);
Mage::unregister('sales_order_place_after');
Mage::register('sales_order_place_after', 1);
$quote = Mage::getModel('sales/quote')->setStoreId($_store->getId());
$quote->assignCustomer($customer);
$quote->setSendCconfirmation($_sendConfirmation);
foreach($_products as $idx => $val) {
$product = Mage::getModel('catalog/product')->load($idx);
$quote->addProduct($product, new Varien_Object($val));
}
$quote->getBillingAddress()->addData($orderData['order']['billing_address']);
$shippingAddress = $quote->getShippingAddress()->addData($orderData['order']['shipping_address']);
$shippingAddress
->collectTotals()
->setCollectShippingRates(true)
->collectShippingRates()
->setShippingMethod($orderData['order']['shipping_method'])
->setpaymentMethod($orderData['payment']['method'])
;
$quote->getPayment()->importData($orderData['payment']);
$quote->setTotalsCollectedFlag(false)->collectTotals()->save();
$service = Mage::getModel('sales/service_quote', $quote);
$service->submitAll();
try {
$response = $this->_api->ordersFixExternalIds(
array(
'id' => $order['id'],
'externalId' => $service->getOrder()->getId()
)
);
if (
!$response->isSuccessful()
||
200 !== $response->getStatusCode()
) {
Mage::log(
sprintf(
"Orders fix error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
Mage::log("Create: " . $order['externalId'], null, 'history.log');
}
/**
* @param array $order
*/
private function doUpdate($order)
{
$magentoOrder = Mage::getModel('sales/order')->load($order['externalId']);
if (!empty($order['status'])) {
try {
$response = $this->_api->statusesList();
if (
$response->isSuccessful()
&&
200 === $response->getStatusCode()
) {
$code = $order['status'];
$group = $response->statuses[$code]['group'];
if (in_array($group, array('approval', 'assembling', 'delivery'))) {
$magentoOrder->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true);
$magentoOrder->save();
$invoice = $magentoOrder->prepareInvoice()
->setTransactionId($magentoOrder->getId())
->register()
->pay();
$transaction_save = Mage::getModel('core/resource_transaction')
->addObject($invoice)
->addObject($invoice->getOrder());
$transaction_save->save();
}
if (in_array($group, array('complete'))) {
$itemQty = $magentoOrder->getItemsCollection()->count();
Mage::getModel('sales/service_order', $magentoOrder)->prepareShipment($itemQty);
$shipment = new Mage_Sales_Model_Order_Shipment_Api();
$shipment->create($order['externalId']);
}
if (in_array($group, array('cancel'))) {
$magentoOrder->setState(Mage_Sales_Model_Order::STATE_CANCELED, true);
$magentoOrder->save();
}
Mage::log("Update: " . $order['externalId'], null, 'history.log');
} else {
Mage::log(
sprintf(
"Statuses list error: [HTTP status %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
Mage::log(implode(' :: ', $response['errors']));
}
}
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
}
}
/**
* @param $customer
* @return mixed
*/
private function setCustomerId($customer)
{
$customerId = $this->searchCustomer($customer);
if (is_array($customerId) && !empty($customerId)) {
if ($customerId['success']) {
return $customerId['result'];
} else {
$this->fixCustomer($customerId['result'], $customer['externalId']);
return $customer['externalId'];
}
} else {
$this->createCustomer(
array(
'externalId' => $customer['externalId'],
'firstName' => $customer['firstName'],
'lastName' => isset($customer['lastName']) ? $customer['lastName'] : '',
'patronymic' => isset($customer['patronymic']) ? $customer['patronymic'] : '',
'phones' => isset($customer['phone']) ? array($customer['phone']) : array(),
)
);
return $customer['externalId'];
}
}
/**
* @param $data
* @return array|bool
*/
private function searchCustomer($data)
{
try {
$customers = $this->_api->customersList(
array(
'name' => isset($data['phone']) ? $data['phone'] : $data['name'],
'email' => $data['email']
),
1,
100
);
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log($e->getMessage());
}
if ($customers->isSuccessful()) {
return (count($customers['customers']) > 0)
? $this->defineCustomer($customers['customers'])
: false
;
}
}
private function createCustomer($customer)
{
try {
$this->_api->customersCreate($customer);
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log('RestApi::CustomersCreate::Curl: ' . $e->getMessage());
}
}
private function fixCustomer($id, $extId)
{
try {
$this->_api->customersFixExternalIds(
array(
array(
'id' => $id,
'externalId' => $extId
)
)
);
} catch (Retailcrm_Retailcrm_Model_Exception_CurlException $e) {
Mage::log('RestApi::CustomersFixExternalIds::Curl: ' . $e->getMessage());
}
}
private function defineCustomer($searchResult)
{
$result = '';
foreach ($searchResult as $customer) {
if (isset($customer['externalId']) && $customer['externalId'] != '') {
$result = $customer['externalId'];
break;
}
}
return ($result != '')
? array('success' => true, 'result' => $result)
: array('success' => false, 'result' => $searchResult[0]['id']);
}
private function getExchangeTime($datetime)
{
if (empty($datetime)) {
$datetime = new DateTime(
date(
'Y-m-d H:i:s',
strtotime('-1 days', strtotime(date('Y-m-d H:i:s')))
)
);
} else {
$datetime = new DateTime($datetime);
}
return $datetime;
}
private function getCountryCode($string)
{
$country = empty($string) ? 'RU' : $string;
$xmlObj = new Varien_Simplexml_Config(Mage::getModuleDir('etc', 'Retailcrm_Retailcrm').DS.'country.xml');
$xmlData = $xmlObj->getNode();
if ($country != 'RU') {
foreach ($xmlData as $elem) {
if ($elem->name == $country || $elem->english == $country) {
$country = $elem->alpha2;
break;
}
}
}
return (string) $country;
}
}

View file

@ -1,93 +0,0 @@
<?php
/**
* HTTP client
*/
class Retailcrm_Retailcrm_Model_Http_Client
{
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
protected $url;
protected $defaultParameters;
public function __construct($url, array $defaultParameters = array())
{
if (false === stripos($url, 'https://')) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException('API schema requires HTTPS protocol');
}
$this->url = $url;
$this->defaultParameters = $defaultParameters;
$this->retry = 0;
}
/**
* Make HTTP request
*
* @param string $path
* @param string $method (default: 'GET')
* @param array $parameters (default: array())
* @param int $timeout
* @return Retailcrm_Retailcrm_Model_Response_ApiResponse
*/
public function makeRequest($path, $method, array $parameters = array(), $timeout = 90)
{
$allowedMethods = array(self::METHOD_GET, self::METHOD_POST);
if (!in_array($method, $allowedMethods)) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException(sprintf(
'Method "%s" is not valid. Allowed methods are %s',
$method,
implode(', ', $allowedMethods)
));
}
$parameters = array_merge($this->defaultParameters, $parameters);
$url = $this->url . $path;
if (self::METHOD_GET === $method && sizeof($parameters)) {
$url .= '?' . http_build_query($parameters);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, (int) $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
if (self::METHOD_POST === $method) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
}
$responseBody = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno && in_array($errno, array(6, 7, 28, 34, 35)) && $this->retry < 3) {
$errno = null;
$error = null;
$this->retry += 1;
$this->makeRequest(
$path,
$method,
$parameters,
$timeout
);
}
if ($errno) {
throw new Retailcrm_Retailcrm_Model_Exception_CurlException($error, $errno);
}
return new Retailcrm_Retailcrm_Model_Response_ApiResponse($statusCode, $responseBody);
}
}

View file

@ -1,231 +0,0 @@
<?php
class Retailcrm_Retailcrm_Model_Icml
{
protected $_dd;
protected $_eCategories;
protected $_eOffers;
protected $_shop;
public function generate($shop)
{
$this->_shop = $shop;
$string = '<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="'.date('Y-m-d H:i:s').'">
<shop>
<name>'.Mage::app()->getStore($shop)->getName().'</name>
<categories/>
<offers/>
</shop>
</yml_catalog>
';
$xml = new SimpleXMLElement(
$string,
LIBXML_NOENT |LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_PARSEHUGE
);
$this->_dd = new DOMDocument();
$this->_dd->preserveWhiteSpace = false;
$this->_dd->formatOutput = true;
$this->_dd->loadXML($xml->asXML());
$this->_eCategories = $this->_dd->
getElementsByTagName('categories')->item(0);
$this->_eOffers = $this->_dd
->getElementsByTagName('offers')->item(0);
$this->addCategories();
$this->addOffers();
$this->_dd->saveXML();
$baseDir = Mage::getBaseDir();
$shopCode = Mage::app()->getStore($shop)->getCode();
$this->_dd->save($baseDir . DS . 'retailcrm_' . $shopCode . '.xml');
}
private function addCategories()
{
$category = Mage::getModel('catalog/category');
$treeModel = $category->getTreeModel();
$treeModel->load();
$ids = $treeModel->getCollection()->getAllIds();
$categories = array();
if (!empty($ids))
{
foreach ($ids as $id)
{
if ($id > 1) {
$category = Mage::getModel('catalog/category');
$category->load($id);
$categoryData = array(
'id' => $category->getId(),
'name'=> $category->getName(),
'parentId' => $category->getParentId()
);
array_push($categories, $categoryData);
}
}
}
foreach($categories as $category) {
$e = $this->_eCategories->appendChild(
$this->_dd->createElement('category')
);
$e->appendChild($this->_dd->createTextNode($category['name']));
$e->setAttribute('id', $category['id']);
if ($category['parentId'] > 1) {
$e->setAttribute('parentId', $category['parentId']);
}
}
}
private function addOffers()
{
$offers = array();
$helper = Mage::helper('retailcrm');
$picUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA);
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addUrlRewrite();
foreach ($collection as $product) {
$offer = array();
$offer['id'] = $product->getId();
$offer['productId'] = $product->getId();
$offer['productActivity'] = $product->isAvailable() ? 'Y' : 'N';
$offer['name'] = $product->getName();
$offer['productName'] = $product->getName();
$offer['initialPrice'] = (float) $product->getPrice();
$offer['url'] = $helper->rewrittenProductUrl(
$product->getId(), $product->getCategoryId(), $this->_shop
);
$offer['picture'] = $picUrl.'catalog/product'.$product->getImage();
$offer['quantity'] = Mage::getModel('cataloginventory/stock_item')
->loadByProduct($product)->getQty();
foreach ($product->getCategoryIds() as $category_id) {
$offer['categoryId'][] = $category_id;
}
$offer['vendor'] = $product->getAttributeText('manufacturer');
$offer['article'] = $product->getSku();
$offer['weight'] = $product->getWeight();
$offers[] = $offer;
}
foreach ($offers as $offer) {
$e = $this->_eOffers->appendChild(
$this->_dd->createElement('offer')
);
$e->setAttribute('id', $offer['id']);
$e->setAttribute('productId', $offer['productId']);
if (!empty($offer['quantity'])) {
$e->setAttribute('quantity', (int) $offer['quantity']);
} else {
$e->setAttribute('quantity', 0);
}
if (!empty($offer['categoryId'])) {
foreach ($offer['categoryId'] as $categoryId) {
$e->appendChild(
$this->_dd->createElement('categoryId')
)->appendChild(
$this->_dd->createTextNode($categoryId)
);
}
} else {
$e->appendChild($this->_dd->createElement('categoryId', 1));
}
$e->appendChild($this->_dd->createElement('productActivity'))
->appendChild(
$this->_dd->createTextNode($offer['productActivity'])
);
$e->appendChild($this->_dd->createElement('name'))
->appendChild(
$this->_dd->createTextNode($offer['name'])
);
$e->appendChild($this->_dd->createElement('productName'))
->appendChild(
$this->_dd->createTextNode($offer['productName'])
);
$e->appendChild($this->_dd->createElement('price'))
->appendChild(
$this->_dd->createTextNode($offer['initialPrice'])
);
if (!empty($offer['purchasePrice'])) {
$e->appendChild($this->_dd->createElement('purchasePrice'))
->appendChild(
$this->_dd->createTextNode($offer['purchasePrice']
)
);
}
if (!empty($offer['picture'])) {
$e->appendChild($this->_dd->createElement('picture'))
->appendChild(
$this->_dd->createTextNode($offer['picture'])
);
}
if (!empty($offer['url'])) {
$e->appendChild($this->_dd->createElement('url'))
->appendChild(
$this->_dd->createTextNode($offer['url']
)
);
}
if (!empty($offer['vendor'])) {
$e->appendChild($this->_dd->createElement('vendor'))
->appendChild(
$this->_dd->createTextNode($offer['vendor']
)
);
}
if (!empty($offer['article'] )) {
$sku = $this->_dd->createElement('param');
$sku->setAttribute('name', 'article');
$sku->setAttribute('code', 'Article');
$sku->appendChild(
$this->_dd->createTextNode($offer['article'])
);
$e->appendChild($sku);
}
if (!empty($offer['weight'] )) {
$weight = $this->_dd->createElement('param');
$weight->setAttribute('name', 'weight');
$weight->setAttribute('code', 'Weight');
$weight->appendChild(
$this->_dd->createTextNode($offer['weight'])
);
$e->appendChild($weight);
}
}
}
}

View file

@ -1,38 +0,0 @@
<?php
/**
* Observer
*
* @author RetailDriver LLC
*/
class Retailcrm_Retailcrm_Model_Observer
{
/**
* Event after order created
*
* @param Varien_Event_Observer $observer
* @return bool
*/
public function orderCreate(Varien_Event_Observer $observer)
{
if (Mage::registry('sales_order_place_after') != 1){//do nothing if the event was dispatched
$order = $observer->getEvent()->getOrder();
Mage::getModel('retailcrm/exchange')->ordersCreate($order);
}
return true;
}
public function exportCatalog()
{
foreach (Mage::app()->getWebsites() as $website) {
foreach ($website->getGroups() as $group) {
Mage::getModel('retailcrm/icml')->generate((int)$group->getId());
}
}
}
public function importHistory()
{
Mage::getModel('retailcrm/exchange')->ordersHistory();
}
}

View file

@ -1,123 +0,0 @@
<?php
/**
* Response from retailCRM API
*/
class Retailcrm_Retailcrm_Model_Response_ApiResponse implements ArrayAccess
{
// HTTP response status code
protected $statusCode;
// response assoc array
protected $response;
public function __construct($statusCode, $responseBody = null)
{
$this->statusCode = (int) $statusCode;
if (!empty($responseBody)) {
$response = json_decode($responseBody, true);
if (!$response && JSON_ERROR_NONE !== ($error = json_last_error())) {
throw new Retailcrm_Retailcrm_Model_Exception_InvalidJsonException(
"Invalid JSON in the API response body. Error code #$error",
$error
);
}
$this->response = $response;
}
}
/**
* Return HTTP response status code
*
* @return int
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* HTTP request was successful
*
* @return bool
*/
public function isSuccessful()
{
return $this->statusCode < 400;
}
/**
* Allow to access for the property throw class method
*
* @param string $name
* @return mixed
*/
public function __call($name, $arguments)
{
// convert getSomeProperty to someProperty
$propertyName = strtolower(substr($name, 3, 1)) . substr($name, 4);
if (!isset($this->response[$propertyName])) {
throw new InvalidArgumentException("Method \"$name\" not found");
}
return $this->response[$propertyName];
}
/**
* Allow to access for the property throw object property
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
if (!isset($this->response[$name])) {
throw new InvalidArgumentException("Property \"$name\" not found");
}
return $this->response[$name];
}
/**
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
throw new BadMethodCallException('This activity not allowed');
}
/**
* @param mixed $offset
*/
public function offsetUnset($offset)
{
throw new BadMethodCallException('This call not allowed');
}
/**
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->response[$offset]);
}
/**
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
if (!isset($this->response[$offset])) {
throw new InvalidArgumentException("Property \"$offset\" not found");
}
return $this->response[$offset];
}
}

View file

@ -1,92 +0,0 @@
<?xml version="1.0"?>
<!--
The MIT License (MIT)
Copyright (c) 2015 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<config>
<modules>
<Retailcrm_Retailcrm>
<version>1.0.0</version>
</Retailcrm_Retailcrm>
</modules>
<global>
<helpers>
<retailcrm>
<class>Retailcrm_Retailcrm_Helper</class>
</retailcrm>
</helpers>
<models>
<retailcrm>
<class>Retailcrm_Retailcrm_Model</class>
</retailcrm>
</models>
<blocks>
<retailcrm>
<class>Retailcrm_Retailcrm_Block</class>
</retailcrm>
</blocks>
<events>
<sales_order_place_after>
<observers>
<retailcrm_retailcrm_model_observer>
<type>singleton</type>
<class>Retailcrm_Retailcrm_Model_Observer</class>
<method>orderCreate</method>
</retailcrm_retailcrm_model_observer>
</observers>
</sales_order_place_after>
</events>
</global>
<crontab>
<jobs>
<icml>
<schedule><cron_expr>* */4 * * *</cron_expr></schedule>
<run><model>retailcrm/observer::exportCatalog</model></run>
</icml>
<history>
<schedule><cron_expr>*/5 * * * *</cron_expr></schedule>
<run><model>retailcrm/observer::importHistory</model></run>
</history>
</jobs>
</crontab>
<adminhtml>
<acl>
<resources>
<admin>
<children>
<system>
<children>
<config>
<children>
<retailcrm>
<title>Store RetailCRM Module Section</title>
</retailcrm>
</children>
</config>
</children>
</system>
</children>
</admin>
</resources>
</acl>
</adminhtml>
</config>

View file

@ -1,105 +0,0 @@
<?xml version="1.0"?>
<!--
The MIT License (MIT)
Copyright (c) 2015 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<config>
<tabs>
<retailcrm_extension>
<label>RetailCRM</label>
<sort_order>1000</sort_order>
</retailcrm_extension>
</tabs>
<sections>
<retailcrm translate="label" module="retailcrm">
<label>Settings</label>
<class>retailcrm-section</class>
<tab>retailcrm_extension</tab>
<frontend_type>text</frontend_type>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<groups>
<general translate="label comment" module="retailcrm">
<expanded>1</expanded>
<label>General</label>
<frontend_type>text</frontend_type>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<fields>
<api_url translate="label comment">
<label>API URL</label>
<frontend_type>text</frontend_type>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<tooltip><![CDATA[https://<i><b>YourCrmName</b></i>.retailcrm.ru]]></tooltip>
</api_url>
<api_key translate="label comment">
<label>API Key</label>
<frontend_type>text</frontend_type>
<sort_order>3</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<tooltip><![CDATA[To generate an API Key, log in to RetailCRM then select Admin > Integration > API Keys]]></tooltip>
</api_key>
</fields>
</general>
<shipping translate="label comment" module="retailcrm">
<expanded>0</expanded>
<label>Shipping</label>
<frontend_type>text</frontend_type>
<sort_order>11</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<frontend_model>retailcrm/adminhtml_system_config_form_fieldset_shipping</frontend_model>
</shipping>
<payment translate="label comment" module="retailcrm">
<expanded>0</expanded>
<label>Payment Method</label>
<frontend_type>text</frontend_type>
<sort_order>12</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<frontend_model>retailcrm/adminhtml_system_config_form_fieldset_payment</frontend_model>
</payment>
<status translate="label comment" module="retailcrm">
<expanded>0</expanded>
<label>Order Statuses</label>
<frontend_type>text</frontend_type>
<sort_order>13</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<frontend_model>retailcrm/adminhtml_system_config_form_fieldset_status</frontend_model>
</status>
</groups>
</retailcrm>
</sections>
</config>

View file

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<!--
The MIT License (MIT)
Copyright (c) 2015 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<config>
<modules>
<Retailcrm_Retailcrm>
<active>true</active>
<codePool>community</codePool>
</Retailcrm_Retailcrm>
</modules>
</config>

68
bin/install.sh Normal file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env bash
if [ -z $ROOT_DIR ]; then
exit 0;
fi
MAGE_ROOT=$ROOT_DIR/../magento2
create_db() {
mysqladmin create "magento2_test" --user="root" --password="root"
}
magento_clone() {
cd ..
git clone https://github.com/magento/magento2
cd magento2
git checkout $BRANCH
touch auth.json
echo '
{
"http-basic": {
"repo.magento.com": {
"username": "<public-key>",
"password": "<private-key>"
}
}
}
' > auth.json
sudo sed -e "s?<public-key>?$PUBLIC_KEY?g" --in-place auth.json
sudo sed -e "s?<private-key>?$PRIVATE_KEY?g" --in-place auth.json
composer install --no-interaction --prefer-dist
composer require retailcrm/api-client-php
}
magento_install() {
cd $MAGE_ROOT
php bin/magento setup:install \
--db-host="localhost" \
--db-name="magento2_test" \
--db-user="root" \
--db-password="root" \
--admin-firstname="admin_firstname" \
--admin-lastname="admin_lastname" \
--admin-email="example@email.com" \
--admin-user="admin" \
--admin-password="admin123" \
--language="en_US" \
--currency="USD" \
--timezone="Europe/Moscow"
}
module_install() {
cd $MAGE_ROOT
mkdir -p app/code/Retailcrm/Retailcrm
cp -R $ROOT_DIR/src/* app/code/Retailcrm/Retailcrm
php bin/magento module:enable Retailcrm_Retailcrm
php bin/magento setup:upgrade
php bin/magento setup:di:compile
}
create_db
magento_clone
magento_install
module_install

View file

@ -0,0 +1,12 @@
<?php
namespace Retailcrm\Retailcrm\Api;
interface ConfigManagerInterface
{
const URL_PATH = 'retailcrm/general/api_url';
const KEY_PATH = 'retailcrm/general/api_key';
const API_VERSION_PATH = 'retailcrm/general/api_version';
public function getConfigValue($path);
}

View file

@ -0,0 +1,8 @@
<?php
namespace Retailcrm\Retailcrm\Api;
interface CustomerManagerInterface
{
public function process(\Magento\Customer\Model\Customer $customer);
}

View file

@ -0,0 +1,8 @@
<?php
namespace Retailcrm\Retailcrm\Api;
interface OrderManagerInterface
{
public function process(\Magento\Sales\Model\Order $order);
}

View file

@ -0,0 +1,18 @@
<?php
namespace Retailcrm\Retailcrm\ApiClient;
class ApiClientFactory
{
/**
* @param $url
* @param $api_key
* @param null $version
*
* @return \RetailCrm\ApiClient
*/
public function create($url, $api_key, $version = null)
{
return new \RetailCrm\ApiClient($url, $api_key, $version);
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config;
class Button extends \Magento\Config\Block\System\Config\Form\Field
{
/**
* @var string
*/
public $_template = 'Retailcrm_Retailcrm::system/config/button.phtml';
/**
* Remove scope label
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $element
* @return string
*/
public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
{
$element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
return parent::render($element);
}
/**
* Return element html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $element
* @return string
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
{
return $this->_toHtml();
}
/**
* Return ajax url for synchronize button
*
* @return string
*/
public function getAjaxSyncUrl()
{
return $this->getUrl('retailcrm_retailcrm/system_config/button');
}
/**
* Generate synchronize button html
*
* @return string
*/
public function getButtonHtml()
{
$button = $this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Button'
)->setData(
[
'id' => 'order_button',
'label' => __('Send'),
]
);
return $button->toHtml();
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Payment extends \Magento\Config\Block\System\Config\Form\Fieldset
{
/**
* Dummy element
*
* @var \Magento\Framework\DataObject
*/
protected $_dummyElement;
/**
* Field renderer
*
* @var \Magento\Config\Block\System\Config\Form\Field
*/
protected $_fieldRenderer;
private $objectFactory;
private $paymentConfig;
private $client;
public function __construct(
\Magento\Backend\Block\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\View\Helper\Js $jsHelper,
\Magento\Payment\Model\Config $paymentConfig,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Magento\Framework\DataObjectFactory $objectFactory,
array $data = []
) {
$this->paymentConfig = $paymentConfig;
$this->client = $client;
$this->objectFactory = $objectFactory;
parent::__construct($context, $authSession, $jsHelper, $data);
}
/**
* Get field renderer
*
* @return \Magento\Config\Block\System\Config\Form\Field
*/
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = $this->getLayout()->getBlockSingleton(
\Magento\Config\Block\System\Config\Form\Field::class
);
}
return $this->_fieldRenderer;
}
/**
* Get dummy element
*
* @return \Magento\Framework\DataObject
*/
protected function _getDummyElement()
{
if (empty($this->_dummyElement)) {
$this->_dummyElement = $this->objectFactory->create(['showInDefault' => 1, 'showInWebsite' => 1]);
}
return $this->_dummyElement;
}
public function render(AbstractElement $element)
{
$html = '';
$htmlError = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$html .= $this->_getHeaderHtml($element);
if ($this->client->isConfigured()) {
$paymentMethods = $this->paymentConfig->getActiveMethods();
foreach ($paymentMethods as $code => $payment) {
$html .= $this->_getFieldHtml($element, $payment);
}
} else {
$html .= $htmlError;
}
$html .= $this->_getFooterHtml($element);
return $html;
}
/**
* Get options values
*
* @return array
*/
private function getValues()
{
$defaultValues = [
[
'value' => '',
'label' => ''
]
];
$values = [];
$response = $this->client->paymentTypesList();
if ($response === false) {
return $defaultValues;
}
if (isset($response['paymentTypes']) && $response->isSuccessful()) {
$paymentsTypes = $response['paymentTypes'];
} else {
return $defaultValues;
}
foreach ($paymentsTypes as $paymentType) {
$values[] = [
'label' => $paymentType['name'],
'value' => $paymentType['code']
];
}
return $values;
}
/**
* Get field html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $fieldset
* @param \Magento\Payment\Api\Data\PaymentMethodInterface $payment
*
* @return string
*/
protected function _getFieldHtml($fieldset, $payment)
{
$configData = $this->getConfigData();
$path = 'retailcrm/' . $fieldset->getId() . '/' . $payment->getCode();
$data = isset($configData[$path]) ? $configData[$path] : [];
$e = $this->_getDummyElement();
$field = $fieldset->addField(
$payment->getCode(),
'select',
[
'name' => 'groups[' . $fieldset->getId() . '][fields][' . $payment->getCode() . '][value]',
'label' => $payment->getTitle(),
'value' => isset($data) ? $data : '',
'values' => $this->getValues(),
'inherit' => true,
'can_use_default_value' => $this->getForm()->canUseDefaultValue($e),
'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e)
]
)->setRenderer(
$this->_getFieldRenderer()
);
return $field->toHtml();
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
class PaymentList extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
/**
* @var $_paymentCms \Retailcrm\Retailcrm\Model\Config\Backend\PaymentCms
*/
protected $_paymentCms;
/**
* @var $_paymentCrm \Retailcrm\Retailcrm\Model\Config\Backend\PaymentCrm
*/
protected $_paymentCrm;
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getPaymentCmsRenderer()
{
if (!$this->_paymentCms) {
$this->_paymentCms = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\PaymentCms',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_paymentCms;
}
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getPaymentCrmRenderer()
{
if (!$this->_paymentCrm) {
$this->_paymentCrm = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\PaymentCrm',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_paymentCrm;
}
/**
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareToRender()
{
$this->addColumn(
'payment_cms',
[
'label' => __('CMS'),
'renderer' => $this->_getPaymentCmsRenderer()
]
);
$this->addColumn(
'payment_crm',
[
'label' => __('CRM'),
'renderer' => $this->_getPaymentCrmRenderer()
]
);
$this->_addAfter = false;
$this->_addButtonLabel = __('Add');
}
/**
*
* @param \Magento\Framework\DataObject $row
* @throws \Magento\Framework\Exception\LocalizedException
* @return void
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$options = [];
$customAttribute = $row->getData('payment_cms');
$key = 'option_' . $this->_getPaymentCmsRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$customAttribute = $row->getData('payment_crm');
$key = 'option_' . $this->_getPaymentCrmRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$row->setData('option_extra_attrs', $options);
}
}

View file

@ -0,0 +1,181 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Shipping extends \Magento\Config\Block\System\Config\Form\Fieldset
{
/**
* Dummy element
*
* @var \Magento\Framework\DataObject
*/
protected $_dummyElement;
/**
* Field renderer
*
* @var \Magento\Config\Block\System\Config\Form\Field
*/
protected $_fieldRenderer;
private $objectFactory;
private $shippingConfig;
private $client;
public function __construct(
\Magento\Backend\Block\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\View\Helper\Js $jsHelper,
\Magento\Shipping\Model\Config $shippingConfig,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Magento\Framework\DataObjectFactory $objectFactory,
array $data = []
) {
$this->shippingConfig = $shippingConfig;
$this->client = $client;
$this->objectFactory = $objectFactory;
parent::__construct($context, $authSession, $jsHelper, $data);
}
/**
* Get field renderer
*
* @return \Magento\Config\Block\System\Config\Form\Field
*/
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = $this->getLayout()->getBlockSingleton(
\Magento\Config\Block\System\Config\Form\Field::class
);
}
return $this->_fieldRenderer;
}
/**
* Get dummy element
*
* @return \Magento\Framework\DataObject
*/
protected function _getDummyElement()
{
if (empty($this->_dummyElement)) {
$this->_dummyElement = $this->objectFactory->create(['showInDefault' => 1, 'showInWebsite' => 1]);
}
return $this->_dummyElement;
}
/**
* Render element
*
* @param AbstractElement $element
* @return string
*/
public function render(AbstractElement $element)
{
$html = '';
$htmlError = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$html .= $this->_getHeaderHtml($element);
if ($this->client->isConfigured()) {
$deliveryMethods = $this->shippingConfig->getActiveCarriers();
foreach ($deliveryMethods as $code => $delivery) {
$html .= $this->_getFieldHtml($element, $delivery);
}
} else {
$html .= $htmlError;
}
$html .= $this->_getFooterHtml($element);
return $html;
}
/**
* Get options values
*
* @return array
*/
private function getValues()
{
$defaultValues = [
[
'value' => '',
'label' => ''
]
];
$values = [];
try {
$response = $this->client->deliveryTypesList();
} catch (\Exception $exception) {
return $defaultValues;
}
if ($response === false) {
return $defaultValues;
}
if (isset($response['deliveryTypes']) && $response->isSuccessful()) {
$deliveryTypes = $response['deliveryTypes'];
} else {
return $defaultValues;
}
foreach ($deliveryTypes as $deliveryType) {
$values[] = [
'label' => $deliveryType['name'],
'value' => $deliveryType['code']
];
}
return $values;
}
/**
* Get field html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $fieldset
* @param \Magento\Shipping\Model\Carrier\AbstractCarrier $shipping
*
* @return string
*/
protected function _getFieldHtml($fieldset, $shipping)
{
$configData = $this->getConfigData();
$path = 'retailcrm/' . $fieldset->getId() . '/' . $shipping->getCarrierCode();
$data = isset($configData[$path]) ? $configData[$path] : [];
$e = $this->_getDummyElement();
$field = $fieldset->addField(
$shipping->getCarrierCode(),
'select',
[
'name' => 'groups[' . $fieldset->getId() . '][fields][' . $shipping->getCarrierCode() . '][value]',
'label' => $shipping->getConfigData('title'),
'value' => isset($data) ? $data : '',
'values' => $this->getValues(),
'inherit' => true,
'can_use_default_value' => $this->getForm()->canUseDefaultValue($e),
'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e)
]
)->setRenderer(
$this->_getFieldRenderer()
);
return $field->toHtml();
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
class ShippingList extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
/**
* @var $_shippingCms \Retailcrm\Retailcrm\Model\Config\Backend\ShippingCms
*/
protected $_shippingCms;
/**
* @var $_shippingCrm \Retailcrm\Retailcrm\Model\Config\Backend\ShippingCrm
*/
protected $_shippingCrm;
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getShippingCmsRenderer()
{
if (!$this->_shippingCms) {
$this->_shippingCms = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\ShippingCms',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_shippingCms;
}
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getShippingCrmRenderer()
{
if (!$this->_shippingCrm) {
$this->_shippingCrm = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\ShippingCrm',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_shippingCrm;
}
/**
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareToRender()
{
$this->addColumn(
'shipping_cms',
[
'label' => __('CMS'),
'renderer' => $this->_getShippingCmsRenderer()
]
);
$this->addColumn(
'shipping_crm',
[
'label' => __('CRM'),
'renderer' => $this->_getShippingCrmRenderer()
]
);
$this->_addAfter = false;
$this->_addButtonLabel = __('Add');
}
/**
*
* @param \Magento\Framework\DataObject $row
* @throws \Magento\Framework\Exception\LocalizedException
* @return void
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$options = [];
$customAttribute = $row->getData('shipping_cms');
$key = 'option_' . $this->_getShippingCmsRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$customAttribute = $row->getData('shipping_crm');
$key = 'option_' . $this->_getShippingCrmRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$row->setData('option_extra_attrs', $options);
}
}

View file

@ -0,0 +1,171 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Site extends \Magento\Config\Block\System\Config\Form\Fieldset
{
/**
* Dummy element
*
* @var \Magento\Framework\DataObject
*/
protected $_dummyElement;
/**
* Field renderer
*
* @var \Magento\Config\Block\System\Config\Form\Field
*/
protected $_fieldRenderer;
private $objectFactory;
private $client;
public function __construct(
\Magento\Backend\Block\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\View\Helper\Js $jsHelper,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Magento\Framework\DataObjectFactory $objectFactory,
array $data = []
) {
$this->client = $client;
$this->objectFactory = $objectFactory;
parent::__construct($context, $authSession, $jsHelper, $data);
}
/**
* Get field renderer
*
* @return \Magento\Config\Block\System\Config\Form\Field
*/
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = $this->getLayout()->getBlockSingleton(
\Magento\Config\Block\System\Config\Form\Field::class
);
}
return $this->_fieldRenderer;
}
/**
* Get dummy element
*
* @return \Magento\Framework\DataObject
*/
protected function _getDummyElement()
{
if (empty($this->_dummyElement)) {
$this->_dummyElement = $this->objectFactory->create(['showInDefault' => 1, 'showInWebsite' => 0]);
}
return $this->_dummyElement;
}
/**
* Render element
*
* @param AbstractElement $element
* @return string
*/
public function render(AbstractElement $element)
{
$html = '';
$htmlError = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$html .= $this->_getHeaderHtml($element);
if ($this->client->isConfigured()) {
$html .= $this->_getFieldHtml($element);
} else {
$html .= $htmlError;
}
$html .= $this->_getFooterHtml($element);
return $html;
}
/**
* Get options values
*
* @return array
*/
private function getValues()
{
$defaultValues = [
[
'value' => '',
'label' => ''
]
];
$values = [];
try {
$response = $this->client->sitesList();
} catch (\Exception $exception) {
return $defaultValues;
}
if ($response === false) {
return $defaultValues;
}
if (isset($response['sites']) && $response->isSuccessful()) {
$sites = $response['sites'];
} else {
return $defaultValues;
}
foreach ($sites as $site) {
$values[] = [
'label' => $site['name'],
'value' => $site['code']
];
}
return $values;
}
/**
* Get field html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $fieldset
* @param \Magento\Shipping\Model\Carrier\AbstractCarrier $shipping
*
* @return string
*/
protected function _getFieldHtml($fieldset)
{
$configData = $this->getConfigData();
$path = 'retailcrm/' . $fieldset->getId() . '/default';
$data = isset($configData[$path]) ? $configData[$path] : [];
$e = $this->_getDummyElement();
$field = $fieldset->addField(
'default',
'select',
[
'name' => 'groups[' . $fieldset->getId() . '][fields][default][value]',
'label' => __('Default site'),
'value' => isset($data) ? $data : '',
'values' => $this->getValues(),
'inherit' => isset($data['inherit']) ? $data['inherit'] : '',
'can_use_default_value' => $this->getForm()->canUseDefaultValue($e),
'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e)
]
)->setRenderer(
$this->_getFieldRenderer()
);
return $field->toHtml();
}
}

View file

@ -0,0 +1,177 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Sites extends \Magento\Config\Block\System\Config\Form\Fieldset
{
/**
* Dummy element
*
* @var \Magento\Framework\DataObject
*/
protected $_dummyElement;
/**
* Field renderer
*
* @var \Magento\Config\Block\System\Config\Form\Field
*/
protected $_fieldRenderer;
private $objectFactory;
private $storeManager;
private $client;
public function __construct(
\Magento\Backend\Block\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\View\Helper\Js $jsHelper,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Magento\Framework\DataObjectFactory $objectFactory,
array $data = []
) {
$this->storeManager = $storeManager;
$this->client = $client;
$this->objectFactory = $objectFactory;
parent::__construct($context, $authSession, $jsHelper, $data);
}
/**
* Get field renderer
*
* @return \Magento\Config\Block\System\Config\Form\Field
*/
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = $this->getLayout()->getBlockSingleton(
\Magento\Config\Block\System\Config\Form\Field::class
);
}
return $this->_fieldRenderer;
}
/**
* Get dummy element
*
* @return \Magento\Framework\DataObject
*/
protected function _getDummyElement()
{
if (empty($this->_dummyElement)) {
$this->_dummyElement = $this->objectFactory->create(['showInDefault' => 1, 'showInWebsite' => 0]);
}
return $this->_dummyElement;
}
/**
* Render element
*
* @param AbstractElement $element
* @return string
*/
public function render(AbstractElement $element)
{
$html = '';
$htmlError = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$html .= $this->_getHeaderHtml($element);
if ($this->client->isConfigured()) {
$website = $this->storeManager->getWebsite($this->getRequest()->getParam('website', 0));
foreach ($website->getStores() as $store) {
$html .= $this->_getFieldHtml($element, $store);
}
} else {
$html .= $htmlError;
}
$html .= $this->_getFooterHtml($element);
return $html;
}
/**
* Get options values
*
* @return array
*/
private function getValues()
{
$defaultValues = [
[
'value' => '',
'label' => ''
]
];
$values = [];
try {
$response = $this->client->sitesList();
} catch (\Exception $exception) {
return $defaultValues;
}
if ($response === false) {
return $defaultValues;
}
if (isset($response['sites']) && $response->isSuccessful()) {
$sites = $response['sites'];
} else {
return $defaultValues;
}
foreach ($sites as $site) {
$values[] = [
'label' => $site['name'],
'value' => $site['code']
];
}
return $values;
}
/**
* Get field html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $fieldset
* @param \Magento\Shipping\Model\Carrier\AbstractCarrier $shipping
*
* @return string
*/
protected function _getFieldHtml($fieldset, $store)
{
$configData = $this->getConfigData();
$path = 'retailcrm/' . $fieldset->getId() . '/' . $store->getCode();
$data = isset($configData[$path]) ? $configData[$path] : [];
$e = $this->_getDummyElement();
$field = $fieldset->addField(
$store->getCode(),
'select',
[
'name' => 'groups[' . $fieldset->getId() . '][fields][' . $store->getCode() . '][value]',
'label' => $store->getName(),
'value' => isset($data) ? $data : '',
'values' => $this->getValues(),
'inherit' => isset($data['inherit']) ? $data['inherit'] : '',
'can_use_default_value' => $this->getForm()->canUseDefaultValue($e),
'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e)
]
)->setRenderer(
$this->_getFieldRenderer()
);
return $field->toHtml();
}
}

View file

@ -0,0 +1,175 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Status extends \Magento\Config\Block\System\Config\Form\Fieldset
{
/**
* Dummy element
*
* @var \Magento\Framework\DataObject
*/
protected $_dummyElement;
/**
* Field renderer
*
* @var \Magento\Config\Block\System\Config\Form\Field
*/
protected $_fieldRenderer;
private $objectFactory;
private $statusCollection;
private $client;
public function __construct(
\Magento\Backend\Block\Context $context,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Framework\View\Helper\Js $jsHelper,
\Magento\Sales\Model\ResourceModel\Order\Status\Collection $statusCollection,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Magento\Framework\DataObjectFactory $objectFactory,
array $data = []
) {
$this->statusCollection = $statusCollection;
$this->client = $client;
$this->objectFactory = $objectFactory;
parent::__construct($context, $authSession, $jsHelper, $data);
}
/**
* Get field renderer
*
* @return \Magento\Config\Block\System\Config\Form\Field
*/
protected function _getFieldRenderer()
{
if (empty($this->_fieldRenderer)) {
$this->_fieldRenderer = $this->getLayout()->getBlockSingleton(
\Magento\Config\Block\System\Config\Form\Field::class
);
}
return $this->_fieldRenderer;
}
/**
* Get dummy element
*
* @return \Magento\Framework\DataObject
*/
protected function _getDummyElement()
{
if (empty($this->_dummyElement)) {
$this->_dummyElement = $this->objectFactory->create(['showInDefault' => 1, 'showInWebsite' => 1]);
}
return $this->_dummyElement;
}
public function render(AbstractElement $element)
{
$html = '';
$htmlError = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$html .= $this->_getHeaderHtml($element);
if ($this->client->isConfigured()) {
$statuses = $this->statusCollection->toOptionArray();
foreach ($statuses as $code => $status) {
$html .= $this->_getFieldHtml($element, $status);
}
} else {
$html .= $htmlError;
}
$html .= $this->_getFooterHtml($element);
return $html;
}
/**
* Get options values
*
* @return array
*/
private function getValues()
{
$defaultValues = [
[
'value' => '',
'label' => ''
]
];
$values = [];
try {
$response = $this->client->statusesList();
} catch (\Exception $exception) {
return $defaultValues;
}
if ($response === false) {
return $defaultValues;
}
if (isset($response['statuses']) && $response->isSuccessful()) {
$statuses = $response['statuses'];
} else {
return $defaultValues;
}
foreach ($statuses as $status) {
$values[] = [
'label' => $status['name'],
'value' => $status['code']
];
}
return $values;
}
/**
* Get field html
*
* @param \Magento\Framework\Data\Form\Element\AbstractElement $fieldset
* @param array $status
*
* @return string
*/
protected function _getFieldHtml($fieldset, $status)
{
$configData = $this->getConfigData();
$path = 'retailcrm/' . $fieldset->getId() . '/' . $status['value'];
$data = isset($configData[$path]) ? $configData[$path] : [];
$e = $this->_getDummyElement();
$field = $fieldset->addField(
$status['value'],
'select',
[
'name' => 'groups[' . $fieldset->getId() . '][fields][' . $status['value'] . '][value]',
'label' => $status['label'],
'value' => isset($data) ? $data : '',
'values' => $this->getValues(),
'inherit' => true,
'can_use_default_value' => $this->getForm()->canUseDefaultValue($e),
'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e)
]
)->setRenderer(
$this->_getFieldRenderer()
);
return $field->toHtml();
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset;
class StatusList extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
/**
* @var $_statusCms \Retailcrm\Retailcrm\Model\Config\Backend\StatusCms
*/
protected $_statusCms;
/**
* @var $_statusCrm \Retailcrm\Retailcrm\Model\Config\Backend\StatusCrm
*/
protected $_statusCrm;
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getStatusCmsRenderer()
{
if (!$this->_statusCms) {
$this->_statusCms = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\StatusCms',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_statusCms;
}
/**
* @return \Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _getStatusCrmRenderer()
{
if (!$this->_statusCrm) {
$this->_statusCrm = $this->getLayout()->createBlock(
'\Retailcrm\Retailcrm\Model\Config\Backend\StatusCrm',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_statusCrm;
}
/**
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareToRender()
{
$this->addColumn(
'status_cms',
[
'label' => __('CMS'),
'renderer' => $this->_getStatusCmsRenderer()
]
);
$this->addColumn(
'status_crm',
[
'label' => __('CRM'),
'renderer' => $this->_getStatusCrmRenderer()
]
);
$this->_addAfter = false;
$this->_addButtonLabel = __('Add');
}
/**
*
* @param \Magento\Framework\DataObject $row
* @throws \Magento\Framework\Exception\LocalizedException
* @return void
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$options = [];
$customAttribute = $row->getData('status_cms');
$key = 'option_' . $this->_getStatusCmsRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$customAttribute = $row->getData('status_crm');
$key = 'option_' . $this->_getStatusCrmRenderer()->calcOptionHash($customAttribute);
$options[$key] = 'selected="selected"';
$row->setData('option_extra_attrs', $options);
}
}

11
src/Block/Display.php Normal file
View file

@ -0,0 +1,11 @@
<?php
namespace Retailcrm\Retailcrm\Block;
class Display extends \Magento\Framework\View\Element\Template
{
public function sayHello()
{
return __('Hello World');
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace Retailcrm\Retailcrm\Block\Frontend;
class DaemonCollector extends \Magento\Framework\View\Element\Template
{
private $customer;
private $helper;
private $storeResolver;
private $js = '';
private $template = <<<EOT
<script type="text/javascript">
(function(_,r,e,t,a,i,l){_['retailCRMObject']=a;_[a]=_[a]||function(){(_[a].q=_[a].q||[]).push(arguments)};_[a].l=1*new Date();l=r.getElementsByTagName(e)[0];i=r.createElement(e);i.async=!0;i.src=t;l.parentNode.insertBefore(i,l)})(window,document,'script','https://collector.retailcrm.pro/w.js','_rc');
{{ code }}
_rc('send', 'pageView');
</script>
EOT;
/**
* DaemonCollector constructor.
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Customer\Model\Session $customerSession
* @param \Magento\Store\Api\StoreResolverInterface $storeResolver
* @param \Retailcrm\Retailcrm\Helper\Data $helper
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Customer\Model\Session $customerSession,
\Magento\Store\Api\StoreResolverInterface $storeResolver,
\Retailcrm\Retailcrm\Helper\Data $helper,
array $data = []
) {
parent::__construct($context, $data);
$this->customer = $customerSession->getCustomer();
$this->storeResolver = $storeResolver;
$this->helper = $helper;
}
/**
* @return string
*/
public function getJs()
{
return $this->js;
}
/**
* @return $this
*/
public function buildScript()
{
$params = array();
if ($this->customer->getId()) {
$params['customerId'] = $this->customer->getId();
}
try {
$siteKey = $this->helper->getSiteKey(
$this->_storeManager->getStore(
$this->storeResolver->getCurrentStoreId()
)->getWebsiteId()
);
} catch (\Magento\Framework\Exception\NoSuchEntityException $entityException) {
return $this;
}
if ($siteKey) {
$this->js = preg_replace(
'/{{ code }}/',
sprintf(
"\t_rc('create', '%s', %s);\n",
$siteKey,
json_encode((object) $params)
),
$this->template
);
}
return $this;
}
}

View file

@ -0,0 +1,117 @@
<?php
namespace Retailcrm\Retailcrm\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Magento\Customer\Model\ResourceModel\Customer\Collection;
use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory;
class CustomersExport extends Command
{
/**
* @var CollectionFactory
*/
private $customerCollectionFactory;
/**
* @var Collection
*/
private $collection;
private $appState;
private $api;
private $helper;
private $serviceCustomer;
public function __construct(
CollectionFactory $customerCollectionFactory,
\Magento\Framework\App\State $appState,
\Retailcrm\Retailcrm\Helper\Proxy $api,
\Retailcrm\Retailcrm\Helper\Data $helper,
\Retailcrm\Retailcrm\Model\Service\Customer $serviceCustomer
) {
$this->appState = $appState;
$this->api = $api;
$this->helper = $helper;
$this->customerCollectionFactory = $customerCollectionFactory;
$this->serviceCustomer = $serviceCustomer;
parent::__construct();
}
protected function configure()
{
$this->setName('retailcrm:customers:export')
->setDescription('Upload archive customers to RetailCRM from Magento')
->addArgument('from', InputArgument::OPTIONAL, 'Beginning order number')
->addArgument('to', InputArgument::OPTIONAL, 'End order number');
parent::configure();
}
/**
* Upload customers to RetailCRM
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws \Exception
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->appState->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);
$arguments = $input->getArguments();
$this->collection = $this->customerCollectionFactory->create();
$this->collection->addAttributeToSelect('*');
if ($arguments['from'] !== null && $arguments['to'] !== null) {
$this->collection->addAttributeToFilter(
[
[
'attribute' => 'entity_id',
'from' => $arguments['from']
],
[
'attribute' => 'entity_id',
'to' => $arguments['to']
]
]
);
}
$customers = $this->collection->getItems();
if (empty($customers)) {
$output->writeln('<comment>Customers not found</comment>');
return 0;
}
/** @var \Magento\Customer\Model\Customer $customer */
foreach ($customers as $customer) {
$ordersToCrm[$customer->getStore()->getId()][] = $this->serviceCustomer->process($customer);
}
foreach ($ordersToCrm as $storeId => $ordersStore) {
$chunked = array_chunk($ordersStore, 50);
unset($ordersStore);
foreach ($chunked as $chunk) {
$this->api->setSite($this->helper->getSite($storeId));
$this->api->customersUpload($chunk);
time_nanosleep(0, 250000000);
}
unset($chunked);
}
$output->writeln('<info>Uploading customers finished</info>');
return 0;
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Retailcrm\Retailcrm\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
class IcmlGenerate extends Command
{
private $icml;
private $storeManager;
private $appState;
public function __construct(
\Retailcrm\Retailcrm\Model\Icml\Icml $icml,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\State $appState
) {
$this->icml = $icml;
$this->storeManager = $storeManager;
$this->appState = $appState;
parent::__construct();
}
protected function configure()
{
$this->setName('retailcrm:icml:generate')
->setDescription('Generating ICML catalog in root directory')
->addArgument('website', InputArgument::OPTIONAL, 'Website id');
parent::configure();
}
/**
* Generate ICML catalog
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws \Exception
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->appState->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);
$arguments = $input->getArguments();
$websites = [];
if (isset($arguments['website'])) {
$websites[] = $this->storeManager->getWebsite($arguments['website']);
} else {
$websites = $this->storeManager->getWebsites();
}
if (!$websites) {
$output->writeln('<comment>Websites not found</comment>');
return 0;
}
foreach ($websites as $website) {
try {
$this->icml->generate($website);
} catch (\Exception $exception) {
$output->writeln('<comment>' . $exception->getMessage() . '</comment>');
return 1;
}
}
return 0;
}
}

View file

@ -0,0 +1,103 @@
<?php
namespace Retailcrm\Retailcrm\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
class OrdersExport extends Command
{
private $orderRepository;
private $searchCriteriaBuilder;
private $appState;
private $serviceOrder;
private $api;
private $helper;
public function __construct(
\Magento\Sales\Model\OrderRepository $orderRepository,
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
\Magento\Framework\App\State $appState,
\Retailcrm\Retailcrm\Model\Service\Order $serviceOrder,
\Retailcrm\Retailcrm\Helper\Proxy $api,
\Retailcrm\Retailcrm\Helper\Data $helper
) {
$this->orderRepository = $orderRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->appState = $appState;
$this->serviceOrder = $serviceOrder;
$this->api = $api;
$this->helper = $helper;
parent::__construct();
}
protected function configure()
{
$this->setName('retailcrm:orders:export')
->setDescription('Upload archive orders to RetailCRM from Magento')
->addArgument('from', InputArgument::OPTIONAL, 'Beginning order number')
->addArgument('to', InputArgument::OPTIONAL, 'End order number');
parent::configure();
}
/**
* Upload orders to RetailCRM
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws \Exception
*
* @return boolean
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->appState->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);
$arguments = $input->getArguments();
if ($arguments['from'] !== null && $arguments['to'] !== null) {
$searchCriteria = $this->searchCriteriaBuilder
->addFilter('increment_id', $arguments['from'], 'from')
->addFilter('increment_id', $arguments['to'], 'to')
->create();
} else {
$searchCriteria = $this->searchCriteriaBuilder->create();
}
$resultSearch = $this->orderRepository->getList($searchCriteria);
$orders = $resultSearch->getItems();
if (empty($orders)) {
$output->writeln('<comment>Orders not found</comment>');
return false;
}
/** @var \Magento\Sales\Model\Order $order */
foreach ($orders as $order) {
$ordersToCrm[$order->getStore()->getId()][] = $this->serviceOrder->process($order);
}
foreach ($ordersToCrm as $storeId => $ordersStore) {
$chunked = array_chunk($ordersStore, 50);
unset($ordersStore);
foreach ($chunked as $chunk) {
$this->api->setSite($this->helper->getSite($storeId));
$this->api->ordersUpload($chunk);
time_nanosleep(0, 250000000);
}
unset($chunked);
}
$output->writeln('<info>Uploading orders finished</info>');
return true;
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Retailcrm\Retailcrm\Controller\Adminhtml\System\Config;
class Button extends \Magento\Backend\App\Action
{
private $order;
private $jsonFactory;
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Retailcrm\Retailcrm\Model\Order\OrderNumber $order
* @param \Magento\Framework\Controller\Result\JsonFactory $jsonFactory
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Retailcrm\Retailcrm\Model\Order\OrderNumber $order,
\Magento\Framework\Controller\Result\JsonFactory $jsonFactory
) {
$this->order = $order;
$this->jsonFactory = $jsonFactory;
parent::__construct($context);
}
/**
* Upload selected orders
*
* @return \Magento\Framework\Controller\Result\Json
*/
public function execute()
{
$numbers = $this->getRequest()->getParam('numbers');
$result = $this->order->exportOrderNumber($numbers);
$resultJson = $this->jsonFactory->create();
return $resultJson->setData($result);
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace Retailcrm\Retailcrm\Controller\Index;
class Display extends \Magento\Framework\App\Action\Action
{
private $pageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory
) {
$this->pageFactory = $pageFactory;
parent::__construct($context);
}
public function execute()
{
return $this->pageFactory->create();
}
}

29
src/Cron/Icml.php Normal file
View file

@ -0,0 +1,29 @@
<?php
namespace Retailcrm\Retailcrm\Cron;
class Icml
{
private $logger;
private $icml;
private $storeManager;
public function __construct(
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
\Retailcrm\Retailcrm\Model\Icml\Icml $icml,
\Magento\Store\Model\StoreManagerInterface $storeManager
) {
$this->logger = $logger;
$this->icml = $icml;
$this->storeManager = $storeManager;
}
public function execute()
{
$websites = $this->storeManager->getWebsites();
foreach ($websites as $website) {
$this->icml->generate($website);
}
}
}

24
src/Cron/Inventories.php Normal file
View file

@ -0,0 +1,24 @@
<?php
namespace Retailcrm\Retailcrm\Cron;
class Inventories
{
private $inventoriesUpload;
private $helper;
public function __construct(
\Retailcrm\Retailcrm\Helper\Data $helper,
\Retailcrm\Retailcrm\Model\Service\InventoriesUpload $InventoriesUpload
) {
$this->helper = $helper;
$this->inventoriesUpload = $InventoriesUpload;
}
public function execute()
{
if ($this->helper->getInventoriesUpload() == true) {
$this->inventoriesUpload->uploadInventory();
}
}
}

23
src/Cron/OrderHistory.php Normal file
View file

@ -0,0 +1,23 @@
<?php
namespace Retailcrm\Retailcrm\Cron;
class OrderHistory
{
private $logger;
private $history;
public function __construct(
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
\Retailcrm\Retailcrm\Model\History\Exchange $history
) {
$this->logger = $logger;
$this->history = $history;
}
public function execute()
{
$this->history->ordersHistory();
$this->logger->writeRow('Cron Works: OrderHistory');
}
}

268
src/Helper/Data.php Normal file
View file

@ -0,0 +1,268 @@
<?php
namespace Retailcrm\Retailcrm\Helper;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\Helper\Context;
use Magento\Store\Model\ScopeInterface;
class Data extends AbstractHelper
{
private $storeManager;
const XML_PATH_RETAILCRM = 'retailcrm/';
const XML_PATH_DEFAULT_SITE = 'retailcrm_site/default';
const XML_PATH_SITES = 'retailcrm_sites/';
const XML_PATH_DAEMON_COLLECTOR = 'daemon_collector/';
const XML_PATH_INVENTORIES = 'inventories_upload/';
public function __construct(
Context $context,
StoreManagerInterface $storeManager
) {
$this->storeManager = $storeManager;
parent::__construct($context);
}
public function getGeneralSettings($setting = null)
{
return $setting === null
? $this->getConfigValue(self::XML_PATH_RETAILCRM . 'general')
: $this->getConfigValue(self::XML_PATH_RETAILCRM . 'general/' . $setting);
}
public function getConfigValue($field, $storeId = null)
{
return $this->scopeConfig->getValue(
$field,
ScopeInterface::SCOPE_STORE,
$storeId
);
}
/**
* Get site code
*
* @param $store
*
* @return mixed|null
* @throws \Exception
*/
public function getSite($store)
{
if (is_int($store)) {
$store = $this->storeManager->getStore($store);
}
$websitesConfig = $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_SITES . $store->getCode(),
ScopeInterface::SCOPE_WEBSITES
);
if (!$websitesConfig) {
$defaultSite = $this->scopeConfig->getValue(self::XML_PATH_RETAILCRM . self::XML_PATH_DEFAULT_SITE);
if (!$defaultSite) {
return null;
}
return $defaultSite;
}
return $websitesConfig;
}
/**
* @return array
*/
public function getMappingSites()
{
$sites = [];
$websites = $this->storeManager->getWebsites();
foreach ($websites as $website) {
foreach ($website->getStores() as $store) {
$site = $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_SITES . $store->getCode(),
ScopeInterface::SCOPE_WEBSITES,
$website->getId()
);
$sites[$site] = $store->getId();
}
}
return $sites;
}
/**
* @param $website
*
* @return array|bool
*/
public function getDaemonCollector($website)
{
$forWebsite = $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_DAEMON_COLLECTOR . 'active',
ScopeInterface::SCOPE_WEBSITES,
$website
);
if ($forWebsite) {
return [
'website' => $website,
'active' => $forWebsite
];
}
$forDefault = $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_DAEMON_COLLECTOR . 'active',
ScopeConfigInterface::SCOPE_TYPE_DEFAULT
);
if ($forDefault) {
return [
'website' => 0,
'active' => $forDefault
];
}
return false;
}
public function getInventoriesUpload()
{
$inventories = $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_INVENTORIES . 'active',
ScopeConfigInterface::SCOPE_TYPE_DEFAULT
);
if ($inventories) {
return true;
}
return false;
}
/**
* @param $website
*
* @return bool|mixed
*/
public function getSiteKey($website)
{
$daemonCollector = $this->getDaemonCollector($website);
if ($daemonCollector === false) {
return false;
}
if ($daemonCollector['active']) {
if ($daemonCollector['website'] > 0) {
return $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_DAEMON_COLLECTOR . 'key',
ScopeInterface::SCOPE_WEBSITES,
$website
);
} else {
return $this->scopeConfig->getValue(
self::XML_PATH_RETAILCRM . self::XML_PATH_DAEMON_COLLECTOR . 'key',
ScopeConfigInterface::SCOPE_TYPE_DEFAULT
);
}
}
return false;
}
/**
* Recursive array filter
*
* @param array $haystack input array
*
* @SuppressWarnings(PHPMD.StaticAccess)
* @SuppressWarnings(PHPMD.ElseExpression)
*
* @return array
*/
public static function filterRecursive($haystack)
{
foreach ($haystack as $key => $value) {
if (is_array($value)) {
$haystack[$key] = self::filterRecursive($haystack[$key]);
}
if ($haystack[$key] === null
|| $haystack[$key] === ''
|| (is_array($haystack[$key]) && empty($haystack[$key]))
) {
unset($haystack[$key]);
} elseif (!is_array($value)) {
$haystack[$key] = trim($value);
}
}
return $haystack;
}
/**
* @return mixed
*/
public function getConfigPayments()
{
$json = $this->scopeConfig->getValue('retailcrm/paymentList/paymentList');
$List = $this->getConfigJsonUnserialize($json);
foreach ($List as $code => $el) {
$payments[$el['payment_cms']] = $el['payment_crm'];
}
return $payments;
}
/**
* @return mixed
*/
public function getCongigShipping()
{
$json = $this->scopeConfig->getValue('retailcrm/shippingList/shippingList');
$shippingList = $this->getConfigJsonUnserialize($json);
foreach ($shippingList as $code => $el) {
$shippings[$el['shipping_cms']] = $el['shipping_crm'];
}
return $shippings;
}
/**
* @return mixed
*/
public function getCongigStatus()
{
$json = $this->scopeConfig->getValue('retailcrm/statusList/statusList');
$List = $this->getConfigJsonUnserialize($json);
foreach ($List as $code => $el) {
$statusList[$el['status_cms']] = $el['status_crm'];
}
return $statusList;
}
/**
* @param $json
*
* @return mixed
*/
public function getConfigJsonUnserialize($json)
{
if (class_exists(\Magento\Framework\Serialize\Serializer\Json::class)) {
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$serializer = $objectManager->create(\Magento\Framework\Serialize\Serializer\Json::class);
return $serializer->unserialize($json);
} else {
return json_decode($json);
}
}
}

176
src/Helper/Proxy.php Normal file
View file

@ -0,0 +1,176 @@
<?php
namespace Retailcrm\Retailcrm\Helper;
use Retailcrm\Retailcrm\Model\Logger\Logger;
use Retailcrm\Retailcrm\Model\Service\ConfigManager;
use Retailcrm\Retailcrm\ApiClient\ApiClientFactory;
class Proxy
{
private $logger;
private $apiClient;
private $url;
private $apiKey;
private $version;
private $apiClientFactory;
private $errorAccount = 'Account does not exist.';
private $errorNotFound = 'Not found';
private $errorApiKey = 'Wrong "apiKey" value.';
/**
* Proxy constructor.
* @param string $pathUrl
* @param string $pathKey
* @param string $pathVersion
* @param ConfigManager $config
* @param Logger $logger
* @param ApiClientFactory $apiClientFactory
*/
public function __construct(
$pathUrl,
$pathKey,
$pathVersion,
ConfigManager $config,
Logger $logger,
ApiClientFactory $apiClientFactory
) {
$this->logger = $logger;
$this->url = $config->getConfigValue($pathUrl);
$this->apiKey = $config->getConfigValue($pathKey);
$this->version = $config->getConfigValue($pathVersion);
$this->apiClientFactory = $apiClientFactory;
if ($this->isConfigured()) {
$this->init();
}
}
public function __call($method, $arguments)
{
try {
$response = call_user_func_array([$this->apiClient->request, $method], $arguments);
if (!$response->isSuccessful()) {
$this->logger->writeRow(
sprintf(
"[HTTP status %s] %s - %s",
$response->getStatusCode(),
$method,
$response->getErrorMsg()
)
);
if (isset($response['errors'])) {
$this->logger->writeRow(implode(' :: ', $response['errors']));
}
}
} catch (\RetailCrm\Exception\CurlException $exception) {
$this->logger->writeRow($exception->getMessage());
return false;
} catch (\RetailCrm\Exception\InvalidJsonException $exception) {
$this->logger->writeRow($exception->getMessage());
return false;
} catch (\InvalidArgumentException $exception) {
$this->logger->writeRow($exception->getMessage());
}
return $response;
}
/**
* Init retailcrm api client
*/
public function init()
{
$this->apiClient = $this->apiClientFactory->create(
$this->url,
$this->apiKey,
$this->version
);
}
/**
* @param $url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* @param $apiKey
*/
public function setApiKey($apiKey)
{
$this->apiKey = $apiKey;
}
/**
* @param $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* @return bool
*/
public function isConfigured()
{
return $this->url && $this->apiKey;
}
/**
* Get API version
*
* @return string
*/
public function getVersion()
{
if (!is_object($this->apiClient)) {
return false;
}
return $this->apiClient->getVersion();
}
/**
* Set site code
*
* @param $site
*/
public function setSite($site)
{
if ($this->isConfigured()) {
$this->apiClient->request->setSite($site);
}
}
/**
* Get site code
*
* @return null | mixed
*/
public function getSite()
{
if ($this->isConfigured()) {
return $this->apiClient->request->getSite();
}
return null;
}
/**
* Get error text message
*
* @param string $property
*
* @return string
*/
public function getErrorText($property)
{
return $this->{$property};
}
}

View file

@ -0,0 +1,145 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
class ApiUrl extends \Magento\Framework\App\Config\Value
{
private $api;
/**
* ApiUrl constructor.
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
* @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
* @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param ApiClient $api
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
ApiClient $api,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
) {
$this->api = $api;
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
}
/**
* Call before save api url
*
* @throws \Magento\Framework\Exception\ValidatorException
*
* @return void
*/
public function beforeSave()
{
$this->setParams([
'url' => $this->getValue(),
'apiKey' => $this->getFieldsetDataValue('api_key'),
'version' => $this->getFieldsetDataValue('api_version')
]);
if (!$this->isUrl($this->getValue())) {
throw new \Magento\Framework\Exception\ValidatorException(__('Invalid CRM url'));
}
if (!$this->isHttps($this->getValue())) {
$this->schemeEdit($this->getValue());
}
if ($this->validateApiUrl($this->api)) {
$this->setValue($this->getValue());
}
parent::beforeSave();
}
/**
* Validate selected api url
*
* @param ApiClient $api
* @param string $apiVersion
*
* @throws \Magento\Framework\Exception\ValidatorException
*
* @return boolean
*/
private function validateApiUrl(ApiClient $api)
{
$response = $api->availableVersions();
if ($response === false) {
throw new \Magento\Framework\Exception\ValidatorException(__('Make sure that the entered data is correct'));
} elseif (!$response->isSuccessful() && $response['errorMsg'] == $api->getErrorText('errorApiKey')) {
throw new \Magento\Framework\Exception\ValidatorException(__('Incorrect API key'));
} elseif (isset($response['errorMsg']) && $response['errorMsg'] == $api->getErrorText('errorAccount')) {
throw new \Magento\Framework\Exception\ValidatorException(__('Incorrect URL of RetailCRM'));
}
return true;
}
/**
* Check url scheme
*
* @param string $url
*
* @return boolean
*/
private function isHttps($url)
{
$url_array = parse_url($url);
if ($url_array['scheme'] === 'https') {
return true;
} else {
return false;
}
}
/**
* Edit scheme from http to https
*
* @param string $url
*
* @return string
*/
private function schemeEdit(&$url)
{
$url_array = parse_url($url);
$url = 'https://' . $url_array['host'];
}
/**
* Check url
*
* @param string $url
*
* @return type
*/
public function isUrl($url)
{
return preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url);
}
/**
* @param array $data
*/
private function setParams(array $data)
{
$this->api->setUrl($data['url']);
$this->api->setApiKey($data['apiKey']);
$this->api->setVersion($data['version']);
$this->api->init();
}
}

View file

@ -0,0 +1,121 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
class ApiVersion extends \Magento\Framework\App\Config\Value
{
private $api;
private $request;
private $integrationModule;
/**
* ApiVersion constructor.
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
* @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
* @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param \Magento\Framework\App\Request\Http $request
* @param \Retailcrm\Retailcrm\Model\Service\IntegrationModule $integrationModule
* @param ApiClient $api
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
\Magento\Framework\App\Request\Http $request,
\Retailcrm\Retailcrm\Model\Service\IntegrationModule $integrationModule,
ApiClient $api,
array $data = []
) {
$this->api = $api;
$this->request = $request;
$this->integrationModule = $integrationModule;
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
}
/**
* Call before save api version
*
* @return void
*/
public function beforeSave()
{
$this->setParams([
'url' => $this->getFieldsetDataValue('api_url'),
'apiKey' => $this->getFieldsetDataValue('api_key'),
'version' => $this->getValue()
]);
$this->validateApiVersion($this->api, $this->getValue());
parent::beforeSave();
}
/**
* Validate selected api version
*
* @param ApiClient $api
* @param string $apiVersion
*
* @throws \Magento\Framework\Exception\ValidatorException
*
* @return void
*/
private function validateApiVersion(ApiClient $api, $apiVersion)
{
$apiVersions = [
'v4' => '4.0',
'v5' => '5.0'
];
$response = $api->availableVersions();
if ($response->isSuccessful()) {
$availableVersions = $response['versions'];
} else {
throw new \Magento\Framework\Exception\ValidatorException(__('Incorrect URL of RetailCRM or API key'));
}
if (isset($availableVersions)) {
if (in_array($apiVersions[$apiVersion], $availableVersions)) {
$this->setValue($this->getValue());
$this->sendModuleConfiguration($api);
} else {
throw new \Magento\Framework\Exception\ValidatorException(
__('The selected API version is unavailable')
);
}
}
}
/**
* @param $api
*/
private function sendModuleConfiguration($api)
{
$this->integrationModule->setApiVersion($api->getVersion());
$this->integrationModule->setAccountUrl($this->request->getUriString());
$this->integrationModule->sendConfiguration($api);
}
/**
* @param array $data
*/
private function setParams(array $data)
{
$this->api->setUrl($data['url']);
$this->api->setApiKey($data['apiKey']);
$this->api->setVersion($data['version']);
$this->api->init();
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class PaymentCms extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Magento\Payment\Model\Config
*/
private $paymentConfig;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* PaymentCms constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param \Magento\Payment\Model\Config $paymentConfig
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Magento\Payment\Model\Config $paymentConfig,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->paymentConfig = $paymentConfig;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$paymentMethods = array();
try {
$paymentMethods = $this->paymentConfig->getActiveMethods();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
$this->addOption( 'null', "not selected");
if ($paymentMethods) {
foreach ($paymentMethods as $code => $payment) {
$this->addOption($payment->getCode(), $payment->getTitle());
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class PaymentCrm extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Retailcrm\Retailcrm\Helper\Proxy
*/
private $client;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* Activation constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->client = $client;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$paymentsTypes = array();
try {
$response = $this->client->paymentTypesList();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
if (isset($response) && $response->isSuccessful()) {
$paymentsTypes = $response['paymentTypes'];
}
$this->addOption( 'null', "not selected");
if ($paymentsTypes) {
foreach ($paymentsTypes as $paymentsType) {
$this->addOption($paymentsType['code'], $paymentsType['name']);
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class ShippingCms extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Magento\Shipping\Model\Config
*/
private $shippingConfig;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* ShippingColumn constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param \Magento\Shipping\Model\Config $shippingConfig
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Magento\Shipping\Model\Config $shippingConfig,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->shippingConfig = $shippingConfig;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$deliveryMethods = array();
try {
$deliveryMethods = $this->shippingConfig->getActiveCarriers();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
$this->addOption( 'null', "not selected");
if ($deliveryMethods) {
foreach ($deliveryMethods as $code => $delivery) {
$this->addOption($delivery->getCarrierCode(), $delivery->getConfigData('title'));
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class ShippingCrm extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Retailcrm\Retailcrm\Helper\Proxy
*/
private $client;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* Activation constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->client = $client;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$deliveryTypes = array();
try {
$response = $this->client->deliveryTypesList();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
if (isset($response) && $response->isSuccessful()) {
$deliveryTypes = $response['deliveryTypes'];
}
$this->addOption( 'null', "not selected");
if ($deliveryTypes) {
foreach ($deliveryTypes as $deliveryType) {
$this->addOption($deliveryType['code'], $deliveryType['name']);
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class StatusCms extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Magento\Sales\Model\ResourceModel\Order\Status\Collection
*/
private $statusCollection;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* StatusCms constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param \Magento\Sales\Model\ResourceModel\Order\Status\Collection $statusCollection
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Magento\Sales\Model\ResourceModel\Order\Status\Collection $statusCollection,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->statusCollection = $statusCollection;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$statuses = array();
try {
$statuses = $this->statusCollection->toOptionArray();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
$this->addOption( 'null', "not selected");
if ($statuses) {
foreach ($statuses as $code => $status) {
$this->addOption( $status['value'], $status['label']);
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace Retailcrm\Retailcrm\Model\Config\Backend;
class StatusCrm extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Retailcrm\Retailcrm\Helper\Proxy
*/
private $client;
/**
* @var \Retailcrm\Retailcrm\Model\Logger\Logger
*/
private $logger;
/**
* Activation constructor.
*
* @param \Magento\Framework\View\Element\Context $context
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Retailcrm\Retailcrm\Helper\Proxy $client,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
array $data = []
) {
parent::__construct($context, $data);
$this->client = $client;
$this->logger = $logger;
}
/**
* @param string $value
* @return Magently\Tutorial\Block\Adminhtml\Form\Field\Activation
*/
public function setInputName($value)
{
return $this->setName($value);
}
/**
* Parse to html.
*
* @return mixed
*/
public function _toHtml()
{
if (!$this->getOptions()) {
$statuses = array();
try {
$response = $this->client->statusesList();
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
if (isset($response) && $response->isSuccessful()) {
$statuses = $response['statuses'];
}
$this->addOption( 'null', "not selected");
if ($statuses) {
foreach ($statuses as $status) {
$this->addOption($status['code'], $status['name']);
}
}
}
return parent::_toHtml();
}
}

View file

@ -0,0 +1,737 @@
<?php
namespace Retailcrm\Retailcrm\Model\History;
class Exchange
{
private $api;
private $config;
private $helper;
private $logger;
private $resourceConfig;
private $customerFactory;
private $quote;
private $customerRepository;
private $product;
private $shipconfig;
private $quoteManagement;
private $registry;
private $cacheTypeList;
private $order;
private $orderManagement;
private $orderInterface;
private $storeManager;
private $regionFactory;
public function __construct(
\Retailcrm\Retailcrm\Helper\Data $helper,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Config\Model\ResourceModel\Config $resourceConfig,
\Magento\Customer\Model\CustomerFactory $customerFactory,
\Magento\Quote\Model\QuoteFactory $quote,
\Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
\Magento\Catalog\Model\Product $product,
\Magento\Shipping\Model\Config $shipconfig,
\Magento\Quote\Model\QuoteManagement $quoteManagement,
\Magento\Framework\Registry $registry,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
\Magento\Sales\Api\Data\OrderInterface $orderInterface,
\Magento\Sales\Api\OrderManagementInterface $orderManagement,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
\Magento\Sales\Model\Order $order,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Directory\Model\RegionFactory $regionFactory,
\Retailcrm\Retailcrm\Helper\Proxy $api
) {
$this->shipconfig = $shipconfig;
$this->logger = $logger;
$this->helper = $helper;
$this->config = $config;
$this->resourceConfig = $resourceConfig;
$this->customerFactory = $customerFactory;
$this->quote = $quote;
$this->customerRepository = $customerRepository;
$this->product = $product;
$this->quoteManagement = $quoteManagement;
$this->registry = $registry;
$this->cacheTypeList = $cacheTypeList;
$this->orderInterface = $orderInterface;
$this->orderManagement = $orderManagement;
$this->order = $order;
$this->storeManager = $storeManager;
$this->regionFactory = $regionFactory;
$this->api = $api;
}
/**
* Get orders history from CRM
*
* @return boolean
*/
public function ordersHistory()
{
if (!$this->api->isConfigured()) {
return false;
}
$this->registry->register('RETAILCRM_HISTORY', true);
$historyFilter = [];
$historyOrder = [];
$historyStart = $this->config->getValue('retailcrm/general/filter_history');
if ($historyStart && $historyStart > 0) {
$historyFilter['sinceId'] = $historyStart;
}
while (true) {
$response = $this->api->ordersHistory($historyFilter);
if ($response === false) {
return false;
}
if (!$response->isSuccessful()) {
return true;
}
$orderH = isset($response['history']) ? $response['history'] : [];
if (empty($orderH)) {
return true;
}
$historyOrder = array_merge($historyOrder, $orderH);
$end = array_pop($orderH);
$historyFilter['sinceId'] = $end['id'];
if ($response['pagination']['totalPageCount'] == 1) {
$this->resourceConfig->saveConfig(
'retailcrm/general/filter_history',
$historyFilter['sinceId'],
'default',
0
);
$this->cacheTypeList->cleanType('config');
$orders = self::assemblyOrder($historyOrder);
$this->logger->writeDump($orders, 'OrderHistory');
$this->processOrders($orders);
return true;
}
}
$this->registry->register('RETAILCRM_HISTORY', false);
}
/**
* Process orders
*
* @param array $orders
*
* @return void
*/
private function processOrders($orders)
{
$this->logger->writeDump($orders, 'processOrders');
if (!empty($orders)) {
foreach ($orders as $order) {
if (isset($order['externalId']) && !empty($order['externalId'])) {
$this->doUpdate($order);
} else {
$this->doCreate($order);
}
}
}
}
/**
* Create new order from CRM
*
* @param array $order
*
* @return void
*/
private function doCreate($order)
{
$this->logger->writeDump($order, 'doCreate');
$payments = $this->helper->getConfigPayments();
$shippings = $this->helper->getCongigShipping();
$sites = $this->helper->getMappingSites();
if ($sites && in_array($order['site'], $sites)) {
$store = $this->storeManager->getStore($sites[$order['site']]);
$websiteId = $store->getWebsiteId();
} else {
$store = $this->storeManager->getStore();
$websiteId = $this->storeManager->getStore()->getWebsiteId();
}
$region = $this->regionFactory->create();
$customer = $this->customerFactory->create();
$customer->setWebsiteId($websiteId);
if (isset($order['customer']['externalId'])) {
$customer = $this->customerRepository->getById($order['customer']['externalId']);
}
if (!$customer->getId()) {
//If not avilable then create this customer
$customer->setWebsiteId($websiteId)
->setStore($store)
->setFirstname($order['firstName'])
->setLastname($order['lastName'])
->setEmail($order['email'])
->setPassword($order['email']);
try {
$this->customerRepository->save($customer);
} catch (\Exception $exception) {
$this->logger->writeRow($exception->getMessage());
}
$this->api->customersFixExternalIds(
[
[
'id' => $order['customer']['id'],
'externalId' => $customer->getId()
]
]
);
}
//Create object of quote
$quote = $this->quote->create();
//set store for which you create quote
$quote->setStore($store);
// if you have allready buyer id then you can load customer directly
$customer = $this->customerRepository->getById($customer->getId());
$quote->setCurrency();
$quote->assignCustomer($customer); //Assign quote to customer
$manager = \Magento\Framework\App\ObjectManager::getInstance();
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
$productRepository = $manager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
$ditems = [];
foreach ($order['items'] as $item) {
if (!isset($ditems[$item['offer']['externalId']]['quantity'])) {
$ditems[$item['offer']['externalId']] = [
'quantity' => null,
'discountTotal' => null,
'initialPrice' => null,
'price_sum' => null,
'price_item' => null
];
}
$ditems[$item['offer']['externalId']]['quantity'] += $item['quantity'];
$ditems[$item['offer']['externalId']]['discountTotal'] += $item['quantity'] * $item['discountTotal'];
$ditems[$item['offer']['externalId']]['initialPrice'] = (float)$item['initialPrice'];
$ditems[$item['offer']['externalId']]['price_sum'] = $ditems[$item['offer']['externalId']]['initialPrice'] * $ditems[$item['offer']['externalId']]['quantity'] - $ditems[$item['offer']['externalId']]['discountTotal'];
$ditems[$item['offer']['externalId']]['price_item'] = $ditems[$item['offer']['externalId']]['price_sum'] / $ditems[$item['offer']['externalId']]['quantity'];
}
//add items in quote
foreach ($ditems as $id =>$item) {
$product = $productRepository->getById($id,false, $store->getId(), false);
$product->setPrice($item['initialPrice']);
$quote->addProduct(
$product,
(int)$item['quantity']
);
}
$products = [];
foreach ($ditems as $id => $item) {
$products[$id] = ['product_id'=>$id,'qty' => $item['quantity']];
}
$orderData = [
'currency_id' => $this->storeManager->getStore()->getCurrentCurrency()->getCode(),
'email' => $order['email'],
'shipping_address' => [
'firstname' => $order['firstName'],
'lastname' => $order['lastName'],
'street' => $order['delivery']['address']['street'],
'city' => $order['delivery']['address']['city'],
'country_id' => $order['countryIso'],
'region' => $order['delivery']['address']['region'],
'postcode' => $order['delivery']['address']['index'],
'telephone' => $order['phone'],
'save_in_address_book' => 1
],
'items'=> $products
];
$region->loadByName($order['delivery']['address']['region'], $order['countryIso']);
if ($region->getId()) {
$orderData['shipping_address']['region_id'] = $region->getId();
}
$shippings = array_flip(array_filter($shippings));
$payments = array_flip(array_filter($payments));
$ShippingMethods = $this->getAllShippingMethodsCode($shippings[$order['delivery']['code']]);
//Set Address to quote
$quote->getBillingAddress()->addData($orderData['shipping_address']);
$quote->getShippingAddress()->addData($orderData['shipping_address']);
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setCollectShippingRates(true)
->collectShippingRates()
->setShippingMethod($ShippingMethods);
if ($this->api->getVersion() == 'v4') {
$paymentType = $order['paymentType'];
} elseif ($this->api->getVersion() == 'v5') {
if ($order['payments']) {
$paymentType = $this->getPaymentMethod($order['payments']);
}
}
$quote->setPaymentMethod($payments[$paymentType]);
$quote->setInventoryProcessed(false);
/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
$quoteRepository = $manager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
$quoteRepository->save($quote);
// Set Sales Order Payment
$quote->getPayment()->importData(['method' => $payments[$paymentType]]);
// Collect Totals & Save Quote
$quote->collectTotals();
$quoteRepository->save($quote);
// Create Order From Quote
$magentoOrder = $this->quoteManagement->submit($quote);
$increment_id = $magentoOrder->getId();
$this->api->ordersFixExternalIds(
[
[
'id' => $order['id'],
'externalId' => $increment_id
]
]
);
}
/**
* Create old edited order
*
* @param array $order
*
* @return void
*/
private function doCreateUp($order)
{
$manager = \Magento\Framework\App\ObjectManager::getInstance();
$this->logger->writeDump($order, 'doCreateUp');
$response = $this->api->ordersGet($order['id'], $by = 'id');
if (!$response->isSuccessful()) {
return;
}
if (isset($response['order'])) {
$order = $response['order'];
}
$payments = $this->helper->getConfigPayments();
$shippings = $this->helper->getCongigShipping();
$region = $this->regionFactory->create();
$sites = $this->helper->getMappingSites();
if ($sites && in_array($order['site'], $sites)) {
$store = $this->storeManager->getStore($sites[$order['site']]);
$websiteId = $store->getWebsiteId();
} else {
$store = $this->storeManager->getStore();
$websiteId = $this->storeManager->getStore()->getWebsiteId();
}
$customer = $this->customerFactory->create();
$customer->setWebsiteId($websiteId);
if (isset($order['customer']['externalId'])) {
$customer = $this->customerRepository->getById($order['customer']['externalId']);
}
//Create object of quote
$quote = $this->quote->create();
//set store for which you create quote
$quote->setStore($store);
$quote->setCurrency();
// if you have all ready buyer id then you can load customer directly
if ($customer->getId()) {
$customer = $this->customerRepository->getById($customer->getId());
$quote->assignCustomer($customer); //Assign quote to customer
} else {
$quote->setCustomerEmail($order['email']);
$quote->setCustomerIsGuest(1);
}
$ditems = [];
foreach ($order['items'] as $item) {
if (!isset($ditems[$item['offer']['externalId']]['quantity'])) {
$ditems[$item['offer']['externalId']] = [
'quantity' => null,
'discountTotal' => null,
'initialPrice' => null,
'price_sum' => null,
'price_item' => null
];
}
$ditems[$item['offer']['externalId']]['quantity'] += $item['quantity'];
$ditems[$item['offer']['externalId']]['discountTotal'] += $item['quantity'] * $item['discountTotal'];
$ditems[$item['offer']['externalId']]['initialPrice'] = (float)$item['initialPrice'];
$ditems[$item['offer']['externalId']]['price_sum'] = $ditems[$item['offer']['externalId']]['initialPrice'] * $ditems[$item['offer']['externalId']]['quantity'] - $ditems[$item['offer']['externalId']]['discountTotal'];
$ditems[$item['offer']['externalId']]['price_item'] = $ditems[$item['offer']['externalId']]['price_sum'] / $ditems[$item['offer']['externalId']]['quantity'];
}
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
$productRepository = $manager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
//add items in quote
foreach ($ditems as $id => $item) {
$product = $productRepository->getById($id,false, $store->getId(), false);
$product->setPrice($item['initialPrice']);
$quote->addProduct(
$product,
(int)$item['quantity']
);
}
$products = [];
foreach ($ditems as $id => $item) {
$products[$id] = ['product_id'=>$id,'qty' => $item['quantity']];
}
$orderData = [
'currency_id' => $this->storeManager->getStore()->getCurrentCurrency()->getCode(),
'email' => $order['email'],
'shipping_address' => [
'firstname' => $order['firstName'],
'lastname' => $order['lastName'],
'street' => $order['delivery']['address']['street'],
'city' => $order['delivery']['address']['city'],
'country_id' => $order['countryIso'],//US
'region' => $order['delivery']['address']['region'],
'postcode' => $order['delivery']['address']['index'],
'telephone' => $order['phone'],
'save_in_address_book' => 1
],
'items'=> $products
];
$region->loadByName($order['delivery']['address']['region'], $order['countryIso']);
if ($region->getId()) {
$orderData['shipping_address']['region_id'] = $region->getId();
}
$shippings = array_flip(array_filter($shippings));
$payments = array_flip(array_filter($payments));
$ShippingMethods = $this->getAllShippingMethodsCode($shippings[$order['delivery']['code']]);
//Set Address to quote
$quote->getBillingAddress()->addData($orderData['shipping_address']);
$quote->getShippingAddress()->addData($orderData['shipping_address']);
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setCollectShippingRates(true)
->collectShippingRates()
->setShippingMethod($ShippingMethods);
if ($this->api->getVersion() == 'v4') {
$paymentType = $order['paymentType'];
} elseif ($this->api->getVersion() == 'v5') {
$paymentType = $this->getPaymentMethod($order['payments'], false);
}
$quote->setPaymentMethod($payments[$paymentType]);
$quote->setInventoryProcessed(false);
$originalId = $order['externalId'];
$oldOrder = $this->orderInterface->load($originalId);
$orderDataUp = [
'original_increment_id' => $oldOrder->getIncrementId(),
'relation_parent_id' => $oldOrder->getId(),
'relation_parent_real_id' => $oldOrder->getIncrementId(),
'edit_increment' => $oldOrder->getEditIncrement() + 1,
'increment_id' => $oldOrder->getIncrementId() . '-' . ($oldOrder->getEditIncrement() + 1)
];
$quote->setReservedOrderId($orderDataUp['increment_id']);
/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
$quoteRepository = $manager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
$quoteRepository->save($quote);
// Set Sales Order Payment
$quote->getPayment()->importData(['method' => $payments[$paymentType]]);
// Collect Totals & Save Quote
$quote->collectTotals();
$quoteRepository->save($quote);
// Create Order From Quote
$magentoOrder = $this->quoteManagement->submit($quote, $orderDataUp);
$oldOrder->setStatus('canceled')->save();
$increment_id = $magentoOrder->getId();
$this->api->ordersFixExternalIds(
[
[
'id' => $order['id'],
'externalId' => $increment_id
]
]
);
}
/**
* Edit order
*
* @param array $order
*
* @return void
*/
private function doUpdate($order)
{
$this->logger->writeDump($order, 'doUpdate');
$Status = $this->helper->getCongigStatus();
$Status = array_flip(array_filter($Status));
$magentoOrder = $this->order->load($order['externalId']);
$magentoOrderArr = $magentoOrder->getData();
$this->logger->writeDump($magentoOrderArr, 'magentoOrderArr');
$this->logger->writeDump($Status, 'status');
if ((!empty($order['order_edit'])) && ($order['order_edit'] == 1)) {
$this->doCreateUp($order);
}
if (!empty($order['status'])) {
$change = $Status[$order['status']];
if ($change == 'canceled') {
$this->orderManagement->cancel($magentoOrderArr['entity_id']);
}
$order_status = $this->order->load($magentoOrder->getId());
$order_status->setStatus($change);
$order_status->save();
}
}
/**
* Assembly orders from history
*
* @param array $orderHistory
*
* @return array $orders
*/
public static function assemblyOrder($orderHistory)
{
$orders = [];
foreach ($orderHistory as $change) {
$orderId = $change['order']['id'];
$change['order'] = self::removeEmpty($change['order']);
if (isset($change['order']['items'])) {
$items = [];
foreach ($change['order']['items'] as $item) {
if (isset($change['created'])) {
$item['create'] = 1;
}
$items[$item['id']] = $item;
}
$change['order']['items'] = $items;
}
if (isset($change['order']['contragent']['contragentType'])) {
$change['order']['contragentType'] = self::newValue($change['order']['contragent']['contragentType']);
unset($change['order']['contragent']);
}
if (isset($orders[$change['order']['id']])) {
$orders[$change['order']['id']] = array_merge($orders[$change['order']['id']], $change['order']);
} else {
$orders[$change['order']['id']] = $change['order'];
}
if ($change['field'] == 'manager_comment') {
$orders[$change['order']['id']][$change['field']] = $change['newValue'];
}
if (($change['field'] != 'status')
&& ($change['field'] != 'country')
&& ($change['field'] != 'manager_comment')
&& ($change['field'] != 'order_product.status')
&& ($change['field'] != 'payment_status')
&& ($change['field'] != 'prepay_sum')
) {
$orders[$change['order']['id']]['order_edit'] = 1;
}
if (isset($change['item'])) {
if (isset($orders[$change['order']['id']]['items'])
&& isset($orders[$change['order']['id']]['items'][$change['item']['id']])
) {
$orders[$change['order']['id']]['items'][$change['item']['id']] = array_merge(
$orders[$change['order']['id']]['items'][$change['item']['id']],
$change['item']
);
} else {
$orders[$change['order']['id']]['items'][$change['item']['id']] = $change['item'];
}
if (empty($change['oldValue']) && $change['field'] == 'order_product') {
$orders[$change['order']['id']]['items'][$change['item']['id']]['create'] = 1;
$orders[$change['order']['id']]['order_edit'] = 1;
unset($orders[$change['order']['id']]['items'][$change['item']['id']]['delete']);
}
if (empty($change['newValue']) && $change['field'] == 'order_product') {
$orders[$change['order']['id']]['items'][$change['item']['id']]['delete'] = 1;
$orders[$change['order']['id']]['order_edit'] = 1;
}
if (!empty($change['newValue']) && $change['field'] == 'order_product.quantity') {
$orders[$change['order']['id']]['order_edit'] = 1;
}
} else {
if (isset($change['created'])) {
$orders[$orderId]['create'] = 1;
}
if (isset($change['deleted'])) {
$orders[$orderId]['deleted'] = 1;
}
}
}
return $orders;
}
/**
* Remove empty elements
*
* @param array $inputArray
*
* @return array $outputArray
*/
public static function removeEmpty($inputArray)
{
$outputArray = [];
if (!empty($inputArray)) {
foreach ($inputArray as $key => $element) {
if (!empty($element) || $element === 0 || $element === '0') {
if (is_array($element)) {
$element = self::removeEmpty($element);
}
$outputArray[$key] = $element;
}
}
}
return $outputArray;
}
/**
* Set new value
*
* @param mixed $value
*
* @return string $value
*/
public static function newValue($value)
{
if (isset($value['code'])) {
return $value['code'];
} else {
return $value;
}
}
/**
* Get shipping methods
*
* @param string $mcode
*
* @return string
*/
public function getAllShippingMethodsCode($mcode)
{
$activeCarriers = $this->shipconfig->getActiveCarriers();
foreach ($activeCarriers as $carrierCode => $carrierModel) {
if ($carrierMethods = $carrierModel->getAllowedMethods()) {
foreach ($carrierMethods as $methodCode => $method) {
$code = $carrierCode . '_'. $methodCode;
if ($mcode == $carrierCode) {
$methods[$mcode] = $code;
}
}
}
}
return $methods[$mcode];
}
/**
* Get payment type for api v5
*
* @param array $payments
* @param boolean $newOrder
*
* @return mixed
*/
private function getPaymentMethod($payments, $newOrder = true)
{
if (count($payments) == 1 || $newOrder) {
$payment = reset($payments);
} elseif (count($payments) > 1 && !$newOrder) {
foreach ($payments as $paymentCrm) {
if (isset($paymentCrm['externalId'])) {
$payment = $paymentCrm;
}
}
}
if (isset($payment)) {
return $payment['type'];
}
return false;
}
}

454
src/Model/Icml/Icml.php Normal file
View file

@ -0,0 +1,454 @@
<?php
namespace Retailcrm\Retailcrm\Model\Icml;
class Icml
{
private $dd;
private $eCategories;
private $eOffers;
private $shop;
private $manager;
private $category;
private $storeManager;
private $StockState;
private $configurable;
private $config;
private $dirList;
private $ddFactory;
private $resourceModelProduct;
private $searchCriteriaBuilder;
private $productRepository;
private $dimensionFields = ['height', 'length', 'width'];
public function __construct(
\Magento\Store\Model\StoreManagerInterface $manager,
\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\CatalogInventory\Api\StockStateInterface $StockState,
\Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurable,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\DomDocument\DomDocumentFactory $ddFactory,
\Magento\Framework\Filesystem\DirectoryList $dirList,
\Magento\Catalog\Model\ResourceModel\Product $resourceModelProduct,
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
\Magento\Catalog\Model\ProductRepository $productRepository
) {
$this->configurable = $configurable;
$this->StockState = $StockState;
$this->storeManager = $storeManager;
$this->category = $categoryCollectionFactory;
$this->manager = $manager;
$this->config = $config;
$this->ddFactory = $ddFactory;
$this->dirList = $dirList;
$this->resourceModelProduct = $resourceModelProduct;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->productRepository = $productRepository;
}
/**
* Generate icml catelog
*
* @param \Magento\Store\Model\Website $website
*
* @return void
*/
public function generate($website)
{
$this->shop = $website;
$string = '<?xml version="1.0" encoding="UTF-8"?>
<yml_catalog date="'.date('Y-m-d H:i:s').'">
<shop>
<name>' . $website->getName() . '</name>
<categories/>
<offers/>
</shop>
</yml_catalog>
';
$xml = simplexml_load_string(
$string,
'\Magento\Framework\Simplexml\Element',
LIBXML_NOENT | LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_PARSEHUGE
);
$this->dd = $this->ddFactory->create();
$this->dd->preserveWhiteSpace = false;
$this->dd->formatOutput = true;
$this->dd->loadXML($xml->asXML());
$this->eCategories = $this->dd
->getElementsByTagName('categories')->item(0);
$this->eOffers = $this->dd
->getElementsByTagName('offers')->item(0);
$this->addCategories();
$this->addOffers();
$this->dd->saveXML();
$this->dd->save($this->dirList->getRoot() . '/retailcrm_' . $website->getCode() . '.xml');
}
/**
* Add product categories in icml catalog
*
* @return void
*/
private function addCategories()
{
$collection = $this->category->create();
$collection->addAttributeToSelect('*');
foreach ($collection as $category) {
if ($category->getId() > 1) {
$e = $this->eCategories->appendChild(
$this->dd->createElement('category')
);
$e->appendChild($this->dd->createElement('name', \htmlspecialchars($category->getName())));
if ($category->getImageUrl()) {
$e->appendChild($this->dd->createElement('picture', \htmlspecialchars($category->getImageUrl())));
}
$e->setAttribute('id', $category->getId());
if ($category->getParentId() > 1) {
$e->setAttribute('parentId', $category->getParentId());
}
}
}
}
/**
* Write products in icml catalog
*
* @return void
*/
private function addOffers()
{
$offers = $this->buildOffers();
foreach ($offers as $offer) {
$this->addOffer($offer);
}
}
/**
* Write product in icml catalog
*
* @param array $offer
*
* @return void
*/
private function addOffer($offer)
{
$e = $this->eOffers->appendChild(
$this->dd->createElement('offer')
);
$e->setAttribute('id', $offer['id']);
$e->setAttribute('productId', $offer['productId']);
if (!empty($offer['quantity'])) {
$e->setAttribute('quantity', (int) $offer['quantity']);
} else {
$e->setAttribute('quantity', 0);
}
if (!empty($offer['categoryId'])) {
foreach ($offer['categoryId'] as $categoryId) {
$e->appendChild(
$this->dd->createElement('categoryId')
)->appendChild(
$this->dd->createTextNode($categoryId)
);
}
} else {
$e->appendChild($this->dd->createElement('categoryId', 1));
}
$e->appendChild($this->dd->createElement('productActivity'))
->appendChild(
$this->dd->createTextNode($offer['productActivity'])
);
$e->appendChild($this->dd->createElement('name'))
->appendChild(
$this->dd->createTextNode($offer['name'])
);
$e->appendChild($this->dd->createElement('productName'))
->appendChild(
$this->dd->createTextNode($offer['productName'])
);
$e->appendChild($this->dd->createElement('price'))
->appendChild(
$this->dd->createTextNode($offer['initialPrice'])
);
if (!empty($offer['purchasePrice'])) {
$e->appendChild($this->dd->createElement('purchasePrice'))
->appendChild(
$this->dd->createTextNode($offer['purchasePrice'])
);
}
if (!empty($offer['picture'])) {
$e->appendChild($this->dd->createElement('picture'))
->appendChild(
$this->dd->createTextNode($offer['picture'])
);
}
if (!empty($offer['url'])) {
$e->appendChild($this->dd->createElement('url'))
->appendChild(
$this->dd->createTextNode($offer['url'])
);
}
if (!empty($offer['vendor'])) {
$e->appendChild($this->dd->createElement('vendor'))
->appendChild(
$this->dd->createTextNode($offer['vendor'])
);
}
if (!empty($offer['dimensions'])) {
$e->appendChild($this->dd->createElement('dimensions'))
->appendChild(
$this->dd->createTextNode($offer['dimensions'])
);
}
if (!empty($offer['weight'])) {
$e->appendChild($this->dd->createElement('weight'))
->appendChild(
$this->dd->createTextNode($offer['weight'])
);
}
if (!empty($offer['params'])) {
foreach ($offer['params'] as $param) {
$paramNode = $this->dd->createElement('param');
$paramNode->setAttribute('name', $param['name']);
$paramNode->setAttribute('code', $param['code']);
$paramNode->appendChild(
$this->dd->createTextNode($param['value'])
);
$e->appendChild($paramNode);
}
}
}
/**
* Build offers array
*
* @return array $offers
*/
private function buildOffers()
{
$offers = [];
$criteria = $this->searchCriteriaBuilder
->addFilter('website_id', $this->shop->getId(), 'eq')
->create();
$collection = $this->productRepository->getList($criteria);
$customAdditionalAttributes = $this->config->getValue('retailcrm/catalog/attributes_to_export_into_icml');
foreach ($collection->getItems() as $product) {
if ($product->getTypeId() == 'simple') {
$offers[] = $this->buildOffer($product, $customAdditionalAttributes);
}
if ($product->getTypeId() == 'configurable') {
$associated_products = $this->getAssociatedProducts($product);
foreach ($associated_products as $associatedProduct) {
$offers[] = $this->buildOffer($product, $customAdditionalAttributes, $associatedProduct);
}
}
}
return $offers;
}
/**
* Build offer array
*
* @param object $product
* @param $customAdditionalAttributes
* @param object $associatedProduct
*
* @return array $offer
*/
private function buildOffer($product, $customAdditionalAttributes, $associatedProduct = null)
{
$offer = [];
$store = $this->shop->getDefaultStore() ? $this->shop->getDefaultStore() : $this->storeManager->getStore();
$picUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$offer['id'] = $associatedProduct === null ? $product->getId() : $associatedProduct->getId();
$offer['productId'] = $product->getId();
if ($associatedProduct === null) {
$offer['productActivity'] = $product->isAvailable() ? 'Y' : 'N';
} else {
$offer['productActivity'] = $associatedProduct->isAvailable() ? 'Y' : 'N';
}
$offer['name'] = $associatedProduct === null ? $product->getName() : $associatedProduct->getName();
$offer['productName'] = $product->getName();
$offer['initialPrice'] = $associatedProduct === null
? $product->getFinalPrice()
: $associatedProduct->getFinalPrice();
$offer['url'] = $product->getUrlInStore();
if ($associatedProduct === null) {
$offer['picture'] = $picUrl . 'catalog/product' . $product->getImage();
} else {
$offer['picture'] = $picUrl . 'catalog/product' . $associatedProduct->getImage();
}
$offer['quantity'] = $associatedProduct === null
? $this->getStockQuantity($product)
: $this->getStockQuantity($associatedProduct);
$offer['categoryId'] = $associatedProduct === null
? $product->getCategoryIds()
: $associatedProduct->getCategoryIds();
$offer['vendor'] = $associatedProduct === null
? $product->getAttributeText('manufacturer')
: $associatedProduct->getAttributeText('manufacturer');
$offer['weight'] = $associatedProduct === null
? $product->getWeight()
: $associatedProduct->getWeight();
$params = $this->getOfferParams($product, $customAdditionalAttributes, $associatedProduct);
$offer['params'] = $params['params'];
$offer['dimensions'] = $params['dimensions'];
unset($params);
return $offer;
}
/**
* Get parameters offers
*
* @param object $product
* @param $customAdditionalAttributes
* @param object $associatedProduct
*
* @return array $params
*/
private function getOfferParams($product, $customAdditionalAttributes, $associatedProduct = null)
{
$params = [];
if (!$customAdditionalAttributes) {
return $params;
}
$attributes = explode(',', $customAdditionalAttributes);
$dimensionsAttrs = [];
$dimensions = '';
foreach ($attributes as $attributeCode) {
if ($this->checkDimension($attributeCode) !== false) {
$dimensionsAttrs += $this->checkDimension($attributeCode);
continue;
}
$attribute = $this->resourceModelProduct->getAttribute($attributeCode);
$attributeValue = $associatedProduct
? $associatedProduct->getData($attributeCode)
: $product->getData($attributeCode);
$attributeText = $attribute->getSource()->getOptionText($attributeValue);
if ($attribute && $attributeValue) {
$params[] = [
'name' => $attribute->getDefaultFrontendLabel(),
'code' => $attributeCode,
'value' => $attributeText ? $attributeText : $attributeValue
];
}
}
if ($dimensionsAttrs && count($dimensionsAttrs) == 3) {
$length = $associatedProduct
? $associatedProduct->getData($dimensionsAttrs['length'])
: $product->getData($dimensionsAttrs['length']);
$width = $associatedProduct
? $associatedProduct->getData($dimensionsAttrs['width'])
: $product->getData($dimensionsAttrs['width']);
$height = $associatedProduct
? $associatedProduct->getData($dimensionsAttrs['height'])
: $product->getData($dimensionsAttrs['height']);
if ($length && $width && $height) {
$dimensions = sprintf(
'%s/%s/%s',
$length,
$width,
$height
);
}
}
return ['params' => $params, 'dimensions' => $dimensions];
}
/**
* Get associated products
*
* @param object $product
*
* @return object
*/
private function getAssociatedProducts($product)
{
return $this->configurable
->getUsedProductCollection($product)
->addAttributeToSelect('*')
->addFilterByRequiredOptions();
}
/**
* Get product stock quantity
*
* @param object $offer
* @return int $quantity
*/
private function getStockQuantity($offer)
{
$quantity = $this->StockState->getStockQty(
$offer->getId(),
$offer->getStore()->getWebsiteId()
);
return $quantity;
}
/**
* @param string $attrCode
*
* @return mixed
*/
private function checkDimension($attrCode)
{
foreach ($this->dimensionFields as $dimensionField) {
if (mb_strpos($attrCode, $dimensionField) !== false) {
return [$dimensionField => $attrCode];
}
}
return false;
}
}

View file

@ -0,0 +1,94 @@
<?php
namespace Retailcrm\Retailcrm\Model\Logger;
class Logger
{
private $logDir;
public function __construct(
\Magento\Framework\Filesystem\DirectoryList $directory
) {
$this->logDir = $directory->getPath('log');
}
/**
* Write data in log file
*
* @param array $data
* @param string $fileName
*
* @return void
*/
public function writeDump($data, $fileName)
{
$filePath = $this->logDir . '/' . $fileName . '.log';
if (!$this->checkSize($filePath)) {
$this->clear($filePath);
}
$logData = [
'date' => date('Y-m-d H:i:s'),
'data' => $data
];
$file = fopen($filePath, "a+");
fwrite($file, print_r($logData, true));
fclose($file);
}
/**
* Write data in log file
*
* @param string $data
* @param string $fileName
*
* @return void
*/
public function writeRow($data, $fileName = 'retailcrm')
{
$filePath = $this->logDir . '/' . $fileName . '.log';
if (!$this->checkSize($filePath)) {
$this->clear($filePath);
}
$nowDate = date('Y-m-d H:i:s');
$logData = "[$nowDate] @ " . $data . "\n";
$file = fopen($filePath, "a+");
fwrite($file, $logData);
fclose($file);
}
/**
* Clear file
*
* @param string $file
*
* @return void
*/
private function clear($file)
{
file_put_contents($file, '');
}
/**
* Check file size
*
* @param string $file
*
* @return boolean
*/
private function checkSize($file)
{
if (!file_exists($file)) {
return true;
} elseif (filesize($file) > 10485760) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Retailcrm\Retailcrm\Model\Observer;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
use Retailcrm\Retailcrm\Helper\Data as Helper;
class Customer implements \Magento\Framework\Event\ObserverInterface
{
private $api;
private $registry;
private $customer;
private $helper;
private $serviceCustomer;
public function __construct(
\Magento\Framework\Registry $registry,
Helper $helper,
ApiClient $api,
\Retailcrm\Retailcrm\Model\Service\Customer $serviceCustomer
) {
$this->api = $api;
$this->helper = $helper;
$this->registry = $registry;
$this->serviceCustomer = $serviceCustomer;
$this->customer = [];
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
if ($this->registry->registry('RETAILCRM_HISTORY') === true
|| !$this->api->isConfigured()
) {
return false;
}
$customer = $observer->getEvent()->getCustomer();
$this->customer = $this->serviceCustomer->process($customer);
$this->api->setSite($this->helper->getSite($customer->getStore()));
$response = $this->api->customersEdit($this->customer);
if ($response === false) {
return false;
}
if (!$response->isSuccessful() && $response->errorMsg == $this->api->getErrorText('errorNotFound')) {
$this->api->customersCreate($this->customer);
}
return $this;
}
/**
* @return array
*/
public function getCustomer()
{
return $this->customer;
}
}

View file

@ -0,0 +1,171 @@
<?php
namespace Retailcrm\Retailcrm\Model\Observer;
use Magento\Framework\Event\Observer;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
use Retailcrm\Retailcrm\Helper\Data as Helper;
class OrderCreate implements \Magento\Framework\Event\ObserverInterface
{
protected $api;
protected $logger;
protected $helper;
private $registry;
private $order;
private $serviceOrder;
private $serviceCustomer;
/**
* Constructor
*
* @param \Magento\Framework\Registry $registry
* @param \Retailcrm\Retailcrm\Model\Logger\Logger $logger
* @param \Retailcrm\Retailcrm\Model\Service\Order $serviceOrder
* @param \Retailcrm\Retailcrm\Model\Service\Customer $serviceCustomer
* @param Helper $helper
* @param ApiClient $api
*/
public function __construct(
\Magento\Framework\Registry $registry,
\Retailcrm\Retailcrm\Model\Logger\Logger $logger,
\Retailcrm\Retailcrm\Model\Service\Order $serviceOrder,
\Retailcrm\Retailcrm\Model\Service\Customer $serviceCustomer,
Helper $helper,
ApiClient $api
) {
$this->logger = $logger;
$this->registry = $registry;
$this->serviceOrder = $serviceOrder;
$this->serviceCustomer = $serviceCustomer;
$this->helper = $helper;
$this->api = $api;
$this->order = [];
}
/**
* Execute send order in CRM
*
* @param Observer $observer
*
* @return mixed
*/
public function execute(Observer $observer)
{
if ($this->registry->registry('RETAILCRM_HISTORY') === true
|| !$this->api->isConfigured()
) {
return false;
}
/** @var \Magento\Sales\Model\Order $order */
$order = $observer->getEvent()->getOrder();
$this->api->setSite($this->helper->getSite($order->getStore()));
if ($this->existsInCrm($order->getId()) === true) {
return false;
}
$this->order = $this->serviceOrder->process($order);
$this->setCustomer($order);
Helper::filterRecursive($this->order);
$this->logger->writeDump($this->order, 'CreateOrder');
$this->api->ordersCreate($this->order);
return $this;
}
/**
* @param \Magento\Sales\Model\Order $order
* @param \Magento\Sales\Model\Order\Address $billingAddress
*/
private function setCustomer($order)
{
if ($order->getCustomerIsGuest() == 1) {
$customer = $this->getCustomerByEmail($order->getCustomerEmail());
if ($customer !== false) {
$this->order['customer']['id'] = $customer['id'];
} else {
$newCustomer = $this->serviceCustomer->prepareCustomerFromOrder($order);
$response = $this->api->customersCreate($newCustomer);
if ($response && isset($response['id'])) {
$this->order['customer']['id'] = $response['id'];
}
}
}
if ($order->getCustomerIsGuest() == 0) {
if ($this->existsInCrm($order->getCustomerId(), 'customersGet')) {
$this->order['customer']['externalId'] = $order->getCustomerId();
} else {
$preparedCustomer = $this->serviceCustomer->process($order->getCustomer());
if ($this->api->customersCreate($preparedCustomer)) {
$this->order['customer']['externalId'] = $order->getCustomerId();
}
}
}
}
/**
* Check exists order or customer in CRM
*
* @param int $id
* @param string $method
* @param string $by
* @param string $site
*
* @return boolean
*/
private function existsInCrm($id, $method = 'ordersGet', $by = 'externalId', $site = null)
{
$response = $this->api->{$method}($id, $by, $site);
if ($response === false) {
return false;
}
if (!$response->isSuccessful() && $response->errorMsg == $this->api->getErrorText('errorNotFound')) {
return false;
}
return true;
}
/**
* Get customer by email from CRM
*
* @param string $email
*
* @return mixed
*/
private function getCustomerByEmail($email)
{
$response = $this->api->customersList(['email' => $email]);
if ($response === false) {
return false;
}
if ($response->isSuccessful() && isset($response['customers'])) {
if (!empty($response['customers'])) {
return reset($response['customers']);
}
}
return false;
}
/**
* @return array
*/
public function getOrder()
{
return $this->order;
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace Retailcrm\Retailcrm\Model\Observer;
use Magento\Framework\Event\Observer;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
use Retailcrm\Retailcrm\Helper\Data as Helper;
class OrderUpdate implements \Magento\Framework\Event\ObserverInterface
{
private $api;
private $config;
private $registry;
private $order;
private $helper;
/**
* Constructor
*
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Framework\Registry $registry
* @param Helper $helper
* @param ApiClient $api
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\Registry $registry,
Helper $helper,
ApiClient $api
) {
$this->config = $config;
$this->registry = $registry;
$this->helper = $helper;
$this->api = $api;
$this->order = [];
}
/**
* Execute update order in CRM
*
* @param Observer $observer
*
* @return mixed
*/
public function execute(Observer $observer)
{
if ($this->registry->registry('RETAILCRM_HISTORY') === true
|| !$this->api->isConfigured()
) {
return false;
}
$order = $observer->getEvent()->getOrder();
if ($order) {
$statusList = $this->helper->getCongigStatus();
$this->order = [
'externalId' => $order->getId(),
'status' => $statusList[$order->getStatus()]
];
if ($order->getBaseTotalDue() == 0) {
if ($this->api->getVersion() == 'v4') {
$this->order['paymentStatus'] = 'paid';
} elseif ($this->api->getVersion() == 'v5') {
$payment = [
'externalId' => $order->getPayment()->getId(),
'status' => 'paid'
];
$this->api->ordersPaymentsEdit($payment);
}
}
Helper::filterRecursive($this->order);
$this->api->setSite($this->helper->getSite($order->getStore()));
$this->api->ordersEdit($this->order);
}
return $this;
}
/**
* @return mixed
*/
public function getOrder()
{
return $this->order;
}
}

View file

@ -0,0 +1,66 @@
<?php
namespace Retailcrm\Retailcrm\Model\Order;
use Retailcrm\Retailcrm\Helper\Data as Helper;
use Retailcrm\Retailcrm\Helper\Proxy as ApiClient;
class OrderNumber
{
private $salesOrder;
private $orderService;
private $helper;
private $api;
public function __construct(
Helper $helper,
ApiClient $api,
\Retailcrm\Retailcrm\Model\Service\Order $orderService,
\Magento\Sales\Api\Data\OrderInterface $salesOrder
) {
$this->api = $api;
$this->helper = $helper;
$this->salesOrder = $salesOrder;
$this->orderService = $orderService;
}
/**
* @param string $orderNumbers
*
* @return array
*/
public function exportOrderNumber($orderNumbers)
{
$ordersId = explode(",", $orderNumbers);
$orders = [];
foreach ($ordersId as $id) {
$magentoOrder = $this->salesOrder->load($id);
$orders[$magentoOrder->getStore()->getId()][] = $this->orderService->process($magentoOrder);
}
foreach ($orders as $storeId => $ordersStore) {
$chunked = array_chunk($ordersStore, 50);
unset($ordersStore);
foreach ($chunked as $chunk) {
$this->api->setSite($this->helper->getSite($storeId));
$response = $this->api->ordersUpload($chunk);
/** @var \RetailCrm\Response\ApiResponse $response */
if (!$response->isSuccessful()) {
return [
'success' => false,
'error' => $response->getErrorMsg()
];
}
time_nanosleep(0, 250000000);
}
unset($chunked);
}
return ['success' => true];
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace Retailcrm\Retailcrm\Model\Service;
class ConfigManager implements \Retailcrm\Retailcrm\Api\ConfigManagerInterface
{
private $config;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $config
) {
$this->config = $config;
}
public function getConfigValue($path)
{
return $this->config->getValue($path);
}
}

View file

@ -0,0 +1,156 @@
<?php
namespace Retailcrm\Retailcrm\Model\Service;
use Retailcrm\Retailcrm\Api\CustomerManagerInterface;
class Customer implements CustomerManagerInterface
{
private $helper;
/**
* Customer constructor.
*
* @param \Retailcrm\Retailcrm\Helper\Data $helper
*/
public function __construct(
\Retailcrm\Retailcrm\Helper\Data $helper
) {
$this->helper = $helper;
}
/**
* Process customer
*
* @param \Magento\Customer\Model\Customer $customer
*
* @return array $preparedCustomer
*/
public function process(\Magento\Customer\Model\Customer $customer)
{
$preparedCustomer = [
'externalId' => $customer->getId(),
'email' => $customer->getEmail(),
'firstName' => $customer->getFirstname(),
'patronymic' => $customer->getMiddlename(),
'lastName' => $customer->getLastname(),
'createdAt' => $customer->getCreatedAt()
];
$address = $this->getAddress($customer);
$phones = $this->getPhones($customer);
if ($address) {
$preparedCustomer['address'] = $address;
}
if ($phones) {
$preparedCustomer['phones'] = $this->getPhones($customer);
}
if ($this->helper->getGeneralSettings('api_version') == 'v5') {
if ($customer->getGender()) {
$preparedCustomer['sex'] = $customer->getGender() == 1 ? 'male' : 'female';
}
$preparedCustomer['birthday'] = $customer->getDob();
}
return $preparedCustomer;
}
/**
* @param \Magento\Sales\Model\Order $order
*
* @return array
*/
public function prepareCustomerFromOrder(\Magento\Sales\Model\Order $order)
{
$billing = $order->getBillingAddress();
$preparedCustomer = [
'email' => $billing->getEmail(),
'firstName' => $billing->getFirstname(),
'patronymic' => $billing->getMiddlename(),
'lastName' => $billing->getLastname(),
'createdAt' => $order->getCreatedAt(),
'address' => [
'countryIso' => $billing->getCountryId(),
'index' => $billing->getPostcode(),
'region' => $billing->getRegion(),
'city' => $billing->getCity(),
'street' => is_array($billing->getStreet())
? implode(', ', $billing->getStreet())
: $billing->getStreet(),
'text' => sprintf(
'%s %s %s %s',
$billing->getPostcode(),
$billing->getRegion(),
$billing->getCity(),
is_array($billing->getStreet())
? implode(', ', $billing->getStreet())
: $billing->getStreet()
)
]
];
if ($billing->getTelephone()) {
$preparedCustomer['phones'] = [
[
'number' => $billing->getTelephone()
]
];
}
return $preparedCustomer;
}
private function getAddress(\Magento\Customer\Model\Customer $customer)
{
$billingAddress = $customer->getDefaultBillingAddress();
if ($billingAddress) {
$address = [
'index' => $billingAddress->getData('postcode'),
'countryIso' => $billingAddress->getData('country_id'),
'region' => $billingAddress->getData('region'),
'city' => $billingAddress->getData('city'),
'street' => $billingAddress->getData('street'),
'text' => sprintf(
'%s %s %s %s',
$billingAddress->getData('postcode'),
$billingAddress->getData('region'),
$billingAddress->getData('city'),
$billingAddress->getData('street')
)
];
return $address;
}
return false;
}
/**
* Set customer phones
*
* @param \Magento\Customer\Model\Customer $customer
*
* @return array $phones
*/
private function getPhones(\Magento\Customer\Model\Customer $customer)
{
$addresses = $customer->getAddressesCollection();
$phones = [];
if (!empty($addresses)) {
foreach ($addresses as $address) {
$phone = [];
$phone['number'] = $address->getTelephone();
$phones[] = $phone;
}
}
return $phones;
}
}

View file

@ -0,0 +1,130 @@
<?php
namespace Retailcrm\Retailcrm\Model\Service;
use Retailcrm\Retailcrm\Helper\Data as Helper;
use Magento\Framework\App\Config\ScopeConfigInterface;
class IntegrationModule
{
const LOGO = 'https://s3.eu-central-1.amazonaws.com/retailcrm-billing/images/5b846b1fef57e-magento.svg';
const INTEGRATION_CODE = 'magento';
const NAME = 'Magento 2';
private $accountUrl = null;
private $apiVersion = 'v5';
private $configuration = [];
private $resourceConfig;
private $clientId;
private $helper;
/**
* IntegrationModule constructor.
*
* @param \Magento\Config\Model\ResourceModel\Config $resourceConfig
* @param \Retailcrm\Retailcrm\Helper\Data $helper
*/
public function __construct(
\Magento\Config\Model\ResourceModel\Config $resourceConfig,
Helper $helper
) {
$this->resourceConfig = $resourceConfig;
$this->helper = $helper;
}
/**
* @param $accountUrl
*/
public function setAccountUrl($accountUrl)
{
$this->accountUrl = $accountUrl;
}
/**
* @param $apiVersion
*/
public function setApiVersion($apiVersion)
{
$this->apiVersion = $apiVersion;
}
/**
* @return array
*/
public function getConfiguration()
{
return $this->configuration;
}
/**
* @param $active
*
* @return void
*/
private function setConfiguration($active)
{
$this->clientId = $this->helper->getGeneralSettings('client_id_in_crm');
if (!$this->clientId) {
$this->clientId = uniqid();
}
if ($this->apiVersion == 'v4') {
$this->configuration = [
'name' => self::NAME,
'code' => self::INTEGRATION_CODE . '-' . $this->clientId,
'logo' => self::LOGO,
'configurationUrl' => $this->accountUrl,
'active' => $active
];
} else {
$this->configuration = [
'clientId' => $this->clientId,
'code' => self::INTEGRATION_CODE . '-' . $this->clientId,
'integrationCode' => self::INTEGRATION_CODE,
'active' => $active,
'name' => self::NAME,
'logo' => self::LOGO,
'accountUrl' => $this->accountUrl
];
}
}
/**
* @param \Retailcrm\Retailcrm\Helper\Proxy $apiClient
* @param boolean $active
*
* @return boolean
*/
public function sendConfiguration($apiClient, $active = true)
{
$this->setConfiguration($active);
if ($this->apiVersion == 'v4') {
$response = $apiClient->marketplaceSettingsEdit(Helper::filterRecursive($this->configuration));
} else {
$response = $apiClient->integrationModulesEdit(Helper::filterRecursive($this->configuration));
}
if (!$response) {
return false;
}
if ($response->isSuccessful() && $active == true) {
$scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT;
$scopeId = 0;
$this->resourceConfig->saveConfig(
Helper::XML_PATH_RETAILCRM . 'general/client_id_in_crm',
$this->clientId,
$scope,
$scopeId
);
return true;
}
return false;
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Retailcrm\Retailcrm\Model\Service;
use Magento\Catalog\Api\ProductRepositoryInterface;
class InventoriesUpload
{
private $productRepo;
private $api;
public function __construct(
ProductRepositoryInterface $productRepo,
\Retailcrm\Retailcrm\Helper\Proxy $api
) {
$this->productRepo = $productRepo;
$this->api = $api;
}
/**
* {@inheritdoc}
*/
public function uploadInventory()
{
if (!$this->api->isConfigured()) {
return false;
}
$page = 1;
do {
$response = $this->api->storeInventories(array(), $page, 250);
if ($response === false || !$response->isSuccessful()) {
return false;
}
foreach ($response['offers'] as $offer) {
if (isset($offer['externalId'])) {
$product = $this->productRepo->getById($offer['externalId']);
$product->setStockData(
['qty' => $offer['quantity'],
'is_in_stock' => $offer['quantity'] > 0]
);
$product->save();
}
}
$totalPageCount = $response['pagination']['totalPageCount'];
$page++;
} while ($page <= $totalPageCount);
return true;
}
}

177
src/Model/Service/Order.php Normal file
View file

@ -0,0 +1,177 @@
<?php
namespace Retailcrm\Retailcrm\Model\Service;
use \Retailcrm\Retailcrm\Helper\Data as Helper;
class Order implements \Retailcrm\Retailcrm\Api\OrderManagerInterface
{
private $productRepository;
private $config;
private $helper;
private $configurableProduct;
public function __construct(
\Magento\Catalog\Model\ProductRepository $productRepository,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableProduct,
Helper $helper
) {
$this->productRepository = $productRepository;
$this->config = $config;
$this->helper = $helper;
$this->configurableProduct = $configurableProduct;
}
/**
* Process order
*
* @param \Magento\Sales\Model\Order $order
*
* @return mixed
*/
public function process(\Magento\Sales\Model\Order $order)
{
$items = $order->getAllItems();
$products = $this->addProducts($items);
$shippingAddress = $order->getShippingAddress();
$shipping = $this->getShippingCode($order->getShippingMethod());
$shipList = $this->helper->getCongigShipping();
$statusList = $this->helper->getCongigStatus();
$paymentList = $this->helper->getConfigPayments();
$preparedOrder = [
'externalId' => $order->getId(),
'number' => $order->getRealOrderId(),
'createdAt' => $order->getCreatedAt(),
'lastName' => $shippingAddress->getLastname(),
'firstName' => $shippingAddress->getFirstname(),
'patronymic' => $shippingAddress->getMiddlename(),
'email' => $shippingAddress->getEmail(),
'phone' => $shippingAddress->getTelephone(),
'status' => $statusList[$order->getStatus()],
'items' => $products,
'delivery' => [
'code' => $shipList[$shipping],
'cost' => $order->getShippingAmount(),
'address' => [
'index' => $shippingAddress->getData('postcode'),
'city' => $shippingAddress->getData('city'),
'countryIso' => $shippingAddress->getData('country_id'),
'street' => $shippingAddress->getData('street'),
'region' => $shippingAddress->getData('region'),
'text' => trim(
',',
implode(
',',
[
$shippingAddress->getData('postcode'),
$shippingAddress->getData('city'),
$shippingAddress->getData('street'),
]
)
)
]
]
];
$codeShop = $this->config->getValue('retailcrm/retailcrm_site/default');
if ($shippingAddress->getData('country_id')) {
$preparedOrder['countryIso'] = $shippingAddress->getData('country_id');
}
if ($this->helper->getGeneralSettings('api_version') == 'v4') {
$preparedOrder['discount'] = abs($order->getDiscountAmount());
$preparedOrder['paymentType'] = $paymentList[$order->getPayment()->getMethodInstance()->getCode()];
} elseif ($this->helper->getGeneralSettings('api_version') == 'v5') {
$preparedOrder['discountManualAmount'] = abs($order->getDiscountAmount());
$payment = [
'type'=> $paymentList[$order->getPayment()->getMethodInstance()->getCode()],
'externalId' => $codeShop.$order->getId(),
'order' => [
'externalId' => $order->getId(),
]
];
if ($order->getBaseTotalDue() == 0) {
$payment['status'] = 'paid';
}
$preparedOrder['payments'][] = $payment;
}
if ($order->getCustomerIsGuest() == 0) {
$preparedOrder['customer']['externalId'] = $order->getCustomerId();
}
return Helper::filterRecursive($preparedOrder);
}
/**
* Get shipping code
*
* @param string $string
*
* @return string
*/
public function getShippingCode($string)
{
$split = array_values(explode('_', $string));
$length = count($split);
$prepare = array_slice($split, 0, $length/2);
return implode('_', $prepare);
}
/**
* Add products in order array
*
* @param $items
*
* @return array
*/
protected function addProducts($items)
{
$products = [];
foreach ($items as $item) {
if ($item->getProductType() == 'configurable') {
$attributesInfo = $item->getProductOptions()['attributes_info'];
$attributes = [];
foreach ($attributesInfo as $attributeInfo) {
$attributes[$attributeInfo['option_id']] = $attributeInfo['option_value'];
}
$product = $this->configurableProduct->getProductByAttributes($attributes, $item->getProduct());
} else {
$product = $item->getProduct();
}
$price = $item->getPrice();
if ($price == 0) {
$magentoProduct = $this->productRepository->getById($item->getProductId());
$price = $magentoProduct->getPrice();
}
$resultProduct = [
'productName' => $item->getName(),
'quantity' => $item->getQtyOrdered(),
'initialPrice' => $price,
'offer' => [
'externalId' => $product ? $product->getId() : ''
]
];
unset($magentoProduct);
unset($price);
$products[] = $resultProduct;
}
return $products;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Retailcrm\Retailcrm\Model\Setting;
class ApiVersions implements \Magento\Framework\Option\ArrayInterface
{
public function toOptionArray()
{
return [
['value' => 'v4', 'label' => 'v4'],
['value' => 'v5', 'label' => 'v5']
];
}
}

View file

@ -0,0 +1,45 @@
<?php
namespace Retailcrm\Retailcrm\Model\Setting;
class Attribute implements \Magento\Framework\Option\ArrayInterface
{
private $entityType;
private $store;
public function __construct(
\Magento\Store\Model\Store $store,
\Magento\Eav\Model\Entity\Type $entityType
) {
$this->store = $store;
$this->entityType = $entityType;
}
public function toOptionArray()
{
$types = [
'text',
'decimal',
'boolean',
'select',
'price'
];
$attributes = $this->entityType->loadByCode('catalog_product')->getAttributeCollection();
$attributes->addFieldToFilter('frontend_input', $types);
$result = [];
foreach ($attributes as $attr) {
if ($attr->getFrontendLabel()) {
$result[] = [
'value' => $attr->getAttributeCode(),
'label' => $attr->getFrontendLabel(),
'title' => $attr->getAttributeCode()
];
}
}
return $result;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Retailcrm\Retailcrm\Model\Setting;
class Select implements \Magento\Framework\Option\ArrayInterface
{
public function toOptionArray()
{
return [
['value' => true, 'label' => __('Yes')],
['value' => false, 'label' => __('No')]
];
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Retailcrm\Retailcrm\Model\Setting;
class Shipping implements \Magento\Framework\Option\ArrayInterface
{
private $entityType;
private $store;
private $config;
private $shippingConfig;
public function __construct(
\Magento\Store\Model\Store $store,
\Magento\Eav\Model\Entity\Type $entityType,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Shipping\Model\Config $shippingConfig
) {
$this->store = $store;
$this->entityType = $entityType;
$this->config = $config;
$this->shippingConfig = $shippingConfig;
}
public function toOptionArray()
{
$activeShipping = $this->shippingConfig->getActiveCarriers();
foreach ($activeShipping as $carrierCode => $carrierModel) {
$options = [];
if ($carrierModel->getAllowedMethods()) {
$carrierMethods = $carrierModel->getAllowedMethods();
foreach ($carrierMethods as $methodCode => $method) {
$code = $carrierCode . '_' . $methodCode;
$options[] = [
'value' => $code,
'label' => $method
];
}
$carrierTitle = $this->config->getValue('carriers/' . $carrierCode . '/title');
}
$methods[] = [
'value' => $options,
'label' => $carrierTitle
];
}
return $methods;
}
}

View file

@ -0,0 +1,17 @@
<?php
namespace Retailcrm\Retailcrm\Model\Setting;
class Status extends \Magento\Config\Model\Config\Backend\Serialized\ArraySerialized
{
public function beforeSave()
{
// For value validations
$exceptions = $this->getValue();
// Validations
$this->setValue($exceptions);
return parent::beforeSave();
}
}

1
src/README.md Normal file
View file

@ -0,0 +1 @@
Magento 2 module for interaction with RetailCRM

26
src/Setup/Uninstall.php Normal file
View file

@ -0,0 +1,26 @@
<?php
namespace Retailcrm\Retailcrm\Setup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class Uninstall implements \Magento\Framework\Setup\UninstallInterface
{
private $apiClient;
private $integrationModule;
public function __construct(
\Retailcrm\Retailcrm\Helper\Proxy $apiClient,
\Retailcrm\Retailcrm\Model\Service\IntegrationModule $integrationModule
) {
$this->apiClient = $apiClient;
$this->integrationModule = $integrationModule;
}
public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$this->integrationModule->setApiVersion($this->apiClient->getVersion());
$this->integrationModule->sendConfiguration($this->apiClient, false);
}
}

View file

@ -0,0 +1,127 @@
<?php
namespace Retailcrm\Retailcrm\Test\Helpers;
use Retailcrm\Retailcrm\Test\TestCase;
class FieldsetTest extends TestCase
{
protected $elementMock;
protected $authSessionMock;
protected $userMock;
protected $requestMock;
protected $urlModelMock;
protected $layoutMock;
protected $helperMock;
protected $groupMock;
protected $objectManager;
protected $context;
protected $form;
protected $testElementId = 'test_element_id';
protected $testFieldSetCss = 'test_fieldset_css';
protected $objectFactory;
protected $secureRenderer;
public function setUp()
{
$this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$factoryMock = $this->createMock(\Magento\Framework\Data\Form\Element\Factory::class);
$collectionFactoryMock = $this->createMock(\Magento\Framework\Data\Form\Element\CollectionFactory::class);
$escaperMock = $this->createMock(\Magento\Framework\Escaper::class);
$formElementMock = $this->createMock(\Magento\Framework\Data\Form\Element\Select::class);
$factoryMock->expects($this->any())->method('create')->willReturn($formElementMock);
$this->objectFactory = $this->objectManager->getObject(\Magento\Framework\DataObjectFactory::class);
$formElementMock->expects($this->any())->method('setRenderer')->willReturn($formElementMock);
$elementCollection = $this->objectManager->getObject(\Magento\Framework\Data\Form\Element\Collection::class);
// element mock
$this->elementMock = $this->getMockBuilder(\Magento\Framework\Data\Form\Element\AbstractElement::class)
->setMethods([
'getId',
'getHtmlId',
'getName',
'getElements',
'getLegend',
'getComment',
'getIsNested',
'getExpanded',
'getForm',
'addField'
])
->setConstructorArgs([$factoryMock, $collectionFactoryMock, $escaperMock])
->getMockForAbstractClass();
$this->elementMock->expects($this->any())
->method('getId')
->willReturn($this->testElementId);
$this->elementMock->expects($this->any())
->method('getHtmlId')
->willReturn($this->testElementId);
$this->elementMock->expects($this->any())
->method('addField')
->willReturn($formElementMock);
$this->elementMock->expects($this->any())
->method('getElements')
->willReturn($elementCollection);
$this->authSessionMock = $this->getMockBuilder(\Magento\Backend\Model\Auth\Session::class)
->setMethods(['getUser'])
->disableOriginalConstructor()
->getMock();
$this->userMock = $this->getMockBuilder(\Magento\User\Model\User::class)
->setMethods(['getExtra'])
->disableOriginalConstructor()
->getMock();
$this->authSessionMock->expects($this->any())
->method('getUser')
->willReturn($this->userMock);
$this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
->disableOriginalConstructor()
->getMock();
$this->requestMock->expects($this->any())
->method('getParam')
->willReturn('Test Param');
$factoryCollection = $this->createMock(\Magento\Framework\Data\Form\Element\CollectionFactory::class);
$elementCollection = $this->createMock(\Magento\Framework\Data\Form\Element\Collection::class);
$factoryCollection->expects($this->any())->method('create')->willReturn($elementCollection);
$rendererMock = $this->createMock(\Magento\Framework\Data\Form\Element\Renderer\RendererInterface::class);
if (class_exists(\Magento\Framework\View\Helper\SecureHtmlRenderer::class)) {
$this->secureRenderer = $this->createMock(\Magento\Framework\View\Helper\SecureHtmlRenderer::class);
$this->secureRenderer->method('renderEventListenerAsTag')
->willReturnCallback(
function (string $event, string $js, string $selector): string {
return "<script>document.querySelector('$selector').$event = function () { $js };</script>";
}
);
$this->secureRenderer->method('renderStyleAsTag')
->willReturnCallback(
function (string $style, string $selector): string {
return "<style>$selector { $style }</style>";
}
);
}
$this->urlModelMock = $this->createMock(\Magento\Backend\Model\Url::class);
$this->layoutMock = $this->createMock(\Magento\Framework\View\Layout::class);
$this->groupMock = $this->createMock(\Magento\Config\Model\Config\Structure\Element\Group::class);
$this->groupMock->expects($this->any())->method('getFieldsetCss')
->will($this->returnValue($this->testFieldSetCss));
$this->context = $this->createMock(\Magento\Backend\Block\Context::class);
$this->context->expects($this->any())->method('getRequest')->willReturn($this->requestMock);
$this->context->expects($this->any())->method('getUrlBuilder')->willReturn($this->urlModelMock);
$this->layoutMock->expects($this->any())->method('getBlockSingleton')->willReturn($rendererMock);
$this->helperMock = $this->createMock(\Magento\Framework\View\Helper\Js::class);
$this->form = $this->createPartialMock(
\Magento\Config\Block\System\Config\Form::class,
//['getElements', 'getRequest']
['getRequest']
);
//$this->form->expects($this->any())->method('getElements')->willReturn($elementCollection);
$this->form->expects($this->any())->method('getRequest')->willReturn($this->requestMock);
}
}

58
src/Test/TestCase.php Normal file
View file

@ -0,0 +1,58 @@
<?php
namespace Retailcrm\Retailcrm\Test;
// backward compatibility with phpunit < v.6
if (!class_exists('\PHPUnit\Framework\TestCase')) {
class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
public function createMock($originalClassName)
{
if (method_exists(\PHPUnit\Framework\TestCase::class, 'createMock')) {
return parent::createMock($originalClassName);
} else {
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->getMock();
}
}
protected function createPartialMock($originalClassName, $methods)
{
if (method_exists(\PHPUnit\Framework\TestCase::class, 'createPartialMock')) {
return parent::createMock($originalClassName);
} else {
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
// ->disallowMockingUnknownTypes()
->setMethods(empty($methods) ? null : $methods)
->getMock();
}
}
}
} else {
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
public function createMock($originalClassName)
{
if (method_exists(\PHPUnit\Framework\TestCase::class, 'createMock')) {
return parent::createMock($originalClassName);
} else {
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->getMock();
}
}
}
}

View file

@ -0,0 +1,130 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Adminhtml\System\Config\Form\Fieldset;
class PaymentTest extends \Retailcrm\Retailcrm\Test\Helpers\FieldsetTest
{
/**
* @param boolean $isSuccessful
* @param boolean $isConfigured
* @dataProvider dataProvider
*/
public function testRender($isSuccessful, $isConfigured)
{
// response
$response = $this->objectManager->getObject(
\RetailCrm\Response\ApiResponse::class,
[
'statusCode' => $isSuccessful ? 200 : 404,
'responseBody' => json_encode($this->getTestResponse())
]
);
// api client mock
$client = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods(
[
'isConfigured',
'paymentTypesList'
]
)
->getMock();
$client->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$client->expects($this->any())
->method('paymentTypesList')
->willReturn($response);
// payment config mock
$paymentConfig = $this->getMockBuilder(\Magento\Payment\Model\Config::class)
->disableOriginalConstructor()
->getMock();
$paymentConfig->expects($this->any())
->method('getActiveMethods')
->willReturn($this->getTestActiveMethods());
$data = [
'authSession' => $this->authSessionMock,
'jsHelper' => $this->helperMock,
'data' => ['group' => $this->groupMock],
'client' => $client,
'paymentConfig' => $paymentConfig,
'context' => $this->context,
'objectFactory' => $this->objectFactory,
'secureRenderer' => $this->secureRenderer
];
$payment = $this->objectManager->getObject(
\Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Payment::class,
$data
);
$payment->setForm($this->form);
$payment->setLayout($this->layoutMock);
$html = $payment->render($this->elementMock);
$this->assertContains($this->testElementId, $html);
$this->assertContains($this->testFieldSetCss, $html);
if (!$isConfigured) {
$expected = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$this->assertContains($expected, $html);
}
}
protected function getTestActiveMethods()
{
$payment = $this->getMockBuilder(\Magento\Payment\Model\MethodInterface::class)
->setMethods(['getData'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$payment->expects($this->any())
->method('getData')
->with('title')
->willReturn('Test Payment');
return ['test_payment' => $payment];
}
private function getTestResponse()
{
return [
'success' => true,
'paymentTypes' => [
[
'code' => 'payment',
'name' => 'Test payment type'
]
]
];
}
public function dataProvider()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => true,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
]
];
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Adminhtml\System\Config\Form\Fieldset;
class ShippingTest extends \Retailcrm\Retailcrm\Test\Helpers\FieldsetTest
{
/**
* @param $isSuccessful
* @param $isConfigured
* @dataProvider dataProvider
*/
public function testRender($isSuccessful, $isConfigured)
{
// response
$response = $this->objectManager->getObject(
\RetailCrm\Response\ApiResponse::class,
[
'statusCode' => $isSuccessful ? 200 : 404,
'responseBody' => json_encode($this->getTestResponse())
]
);
// api client mock
$client = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods(
[
'isConfigured',
'deliveryTypesList'
]
)
->getMock();
$client->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$client->expects($this->any())
->method('deliveryTypesList')
->willReturn($response);
// shipping config mock
$shippingConfig = $this->getMockBuilder(\Magento\Shipping\Model\Config::class)
->disableOriginalConstructor()
->getMock();
$shippingConfig->expects($this->any())
->method('getActiveCarriers')
->willReturn($this->getTestActiveCarriers());
$data = [
'authSession' => $this->authSessionMock,
'jsHelper' => $this->helperMock,
'data' => ['group' => $this->groupMock],
'client' => $client,
'shippingConfig' => $shippingConfig,
'context' => $this->context,
'objectFactory' => $this->objectFactory,
'secureRenderer' => $this->secureRenderer
];
$shipping = $this->objectManager->getObject(
\Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Shipping::class,
$data
);
$shipping->setForm($this->form);
$shipping->setLayout($this->layoutMock);
$html = $shipping->render($this->elementMock);
$this->assertContains($this->testElementId, $html);
$this->assertContains($this->testFieldSetCss, $html);
if (!$isConfigured) {
$expected = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$this->assertContains($expected, $html);
}
}
private function getTestActiveCarriers()
{
$shipping = $this->getMockBuilder(\Magento\Shipping\Model\Carrier\AbstractCarrierInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$shipping->expects($this->any())
->method('getConfigData')
->with('title')
->willReturn('Test Shipping');
return ['test_shipping' => $shipping];
}
private function getTestResponse()
{
return [
'success' => true,
'deliveryTypes' => [
[
'code' => 'delivery',
'name' => 'Test delivery type'
]
]
];
}
public function dataProvider()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => true,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
]
];
}
}

View file

@ -0,0 +1,106 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Adminhtml\System\Config\Form\Fieldset;
class SiteTest extends \Retailcrm\Retailcrm\Test\Helpers\FieldsetTest
{
/**
* @param boolean $isSuccessful
* @param boolean $isConfigured
* @dataProvider dataProvider
*/
public function testRender($isSuccessful, $isConfigured)
{
// response
$response = $this->objectManager->getObject(
\RetailCrm\Response\ApiResponse::class,
[
'statusCode' => $isSuccessful ? 200 : 404,
'responseBody' => json_encode($this->getTestResponse())
]
);
// api client mock
$client = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods(
[
'isConfigured',
'sitesList'
]
)
->getMock();
$client->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$client->expects($this->any())
->method('sitesList')
->willReturn($response);
$data = [
'authSession' => $this->authSessionMock,
'jsHelper' => $this->helperMock,
'data' => ['group' => $this->groupMock],
'client' => $client,
'context' => $this->context,
'objectFactory' => $this->objectFactory,
'secureRenderer' => $this->secureRenderer
];
$site = $this->objectManager->getObject(
\Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Site::class,
$data
);
$site->setForm($this->form);
$site->setLayout($this->layoutMock);
$html = $site->render($this->elementMock);
$this->assertContains($this->testElementId, $html);
$this->assertContains($this->testFieldSetCss, $html);
if (!$isConfigured) {
$expected = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$this->assertContains($expected, $html);
}
}
private function getTestResponse()
{
return [
'success' => true,
'sites' => [
[
'code' => 'payment',
'name' => 'Test site'
]
]
];
}
public function dataProvider()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => true,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
]
];
}
}

View file

@ -0,0 +1,135 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Adminhtml\System\Config\Form\Fieldset;
class SitesTest extends \Retailcrm\Retailcrm\Test\Helpers\FieldsetTest
{
/**
* @param boolean $isSuccessful
* @param boolean $isConfigured
* @dataProvider dataProvider
*/
public function testRender($isSuccessful, $isConfigured)
{
// response
$response = $this->objectManager->getObject(
\RetailCrm\Response\ApiResponse::class,
[
'statusCode' => $isSuccessful ? 200 : 404,
'responseBody' => json_encode($this->getTestResponse())
]
);
// api client mock
$client = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods(
[
'isConfigured',
'sitesList'
]
)
->getMock();
$client->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$client->expects($this->any())
->method('sitesList')
->willReturn($response);
$websiteMock = $this->createMock(\Magento\Store\Model\Website::class);
$websiteMock->expects($this->any())->method('getStores')->willReturn($this->getTestStores());
// payment config mock
$storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$storeManager->expects($this->any())
->method('getWebsite')
->willReturn($websiteMock);
$data = [
'authSession' => $this->authSessionMock,
'jsHelper' => $this->helperMock,
'data' => ['group' => $this->groupMock],
'client' => $client,
'storeManager' => $storeManager,
'context' => $this->context,
'objectFactory' => $this->objectFactory,
'secureRenderer' => $this->secureRenderer
];
$sites = $this->objectManager->getObject(
\Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Sites::class,
$data
);
$sites->setForm($this->form);
$sites->setLayout($this->layoutMock);
$html = $sites->render($this->elementMock);
$this->assertContains($this->testElementId, $html);
$this->assertContains($this->testFieldSetCss, $html);
if (!$isConfigured) {
$expected = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$this->assertContains($expected, $html);
}
}
private function getTestStores()
{
$store = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$store->expects($this->any())
->method('getName')
->willReturn('Test Store');
$store->expects($this->any())
->method('getCode')
->willReturn('test_store_code');
return ['test_site' => $store];
}
private function getTestResponse()
{
return [
'success' => true,
'sites' => [
[
'code' => 'payment',
'name' => 'Test site'
]
]
];
}
public function dataProvider()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => true,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
]
];
}
}

View file

@ -0,0 +1,125 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Adminhtml\System\Config\Form\Fieldset;
class StatusTest extends \Retailcrm\Retailcrm\Test\Helpers\FieldsetTest
{
/**
* @param boolean $isSuccessful
* @param boolean $isConfigured
* @dataProvider dataProvider
*/
public function testRender($isSuccessful, $isConfigured)
{
// response
$response = $this->objectManager->getObject(
\RetailCrm\Response\ApiResponse::class,
[
'statusCode' => $isSuccessful ? 200 : 404,
'responseBody' => json_encode($this->getTestResponse())
]
);
// api client mock
$client = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods(
[
'isConfigured',
'statusesList'
]
)
->getMock();
$client->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$client->expects($this->any())
->method('statusesList')
->willReturn($response);
// status collection mock
$statusCollection = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Status\Collection::class)
->disableOriginalConstructor()
->getMock();
$statusCollection->expects($this->any())
->method('toOptionArray')
->willReturn($this->getTestStatuses());
$data = [
'authSession' => $this->authSessionMock,
'jsHelper' => $this->helperMock,
'data' => ['group' => $this->groupMock],
'client' => $client,
'statusCollection' => $statusCollection,
'context' => $this->context,
'objectFactory' => $this->objectFactory,
'secureRenderer' => $this->secureRenderer
];
$status = $this->objectManager->getObject(
\Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Status::class,
$data
);
$status->setForm($this->form);
$status->setLayout($this->layoutMock);
$html = $status->render($this->elementMock);
$this->assertContains($this->testElementId, $html);
$this->assertContains($this->testFieldSetCss, $html);
if (!$isConfigured) {
$expected = sprintf(
'<div style="margin-left: 15px;"><b><i>%s</i></b></div>',
__('Enter API of your URL and API key')
);
$this->assertContains($expected, $html);
}
}
private function getTestStatuses()
{
$status = [
'label' => 'Test Status',
'value' => 'Test status'
];
return ['test_status' => $status];
}
private function getTestResponse()
{
return [
'success' => true,
'statuses' => [
[
'code' => 'status',
'name' => 'Test status'
]
]
];
}
public function dataProvider()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => true,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
]
];
}
}

View file

@ -0,0 +1,81 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Block\Frontend;
use Retailcrm\Retailcrm\Test\TestCase;
class DaemonCollectorTest extends TestCase
{
private $unit;
private $customer;
const SITE_KEY = 'RC-XXXXXXX-X';
public function setUp()
{
$context = $this->createMock(\Magento\Framework\View\Element\Template\Context::class);
$customerSession = $this->createMock(\Magento\Customer\Model\Session::class);
$storeManager = $this->createMock(\Magento\Store\Model\StoreManager::class);
$storeResolver = $this->createMock(\Magento\Store\Model\StoreResolver::class);
$helper = $this->createMock(\Retailcrm\Retailcrm\Helper\Data::class);
$this->customer = $this->createMock(\Magento\Customer\Model\Customer::class);
$store = $this->createMock(\Magento\Store\Model\Store::class);
$customerSession->expects($this->any())
->method('getCustomer')
->willReturn($this->customer);
$storeResolver->expects($this->any())
->method('getCurrentStoreId')
->willReturn(1);
$store->expects($this->any())
->method('getWebsiteId')
->willReturn(1);
$storeManager->expects($this->any())
->method('getStore')
->willReturn($store);
$helper->expects($this->any())
->method('getSiteKey')
->willReturn(self::SITE_KEY);
$context->expects($this->any())
->method('getStoreManager')
->willReturn($storeManager);
$this->unit = new \Retailcrm\Retailcrm\Block\Frontend\DaemonCollector(
$context,
$customerSession,
$storeResolver,
$helper
);
}
public function testGetJSWithCustomer()
{
$this->customer->expects($this->any())
->method('getId')
->willReturn(1);
$js = $this->unit->buildScript()->getJs();
$this->assertContains('<script type="text/javascript">', $js);
$this->assertContains('</script>', $js);
$this->assertContains('_rc(\'send\', \'pageView\');', $js);
$this->assertContains(self::SITE_KEY, $js);
$this->assertContains('customerId', $js);
}
public function testGetJSWithoutCustomer()
{
$this->customer->expects($this->any())
->method('getId')
->willReturn(null);
$js = $this->unit->buildScript()->getJs();
$this->assertContains('<script type="text/javascript">', $js);
$this->assertContains('</script>', $js);
$this->assertContains('_rc(\'send\', \'pageView\');', $js);
$this->assertContains(self::SITE_KEY, $js);
$this->assertNotContains('customerId', $js);
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Model\Observer;
use Retailcrm\Retailcrm\Test\TestCase;
class CustomerTest extends TestCase
{
private $mockApi;
private $mockResponse;
private $registry;
private $mockObserver;
private $mockEvent;
private $mockCustomer;
private $unit;
private $helper;
private $mockServiceCustomer;
public function setUp()
{
$this->mockApi = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods([
'customersEdit',
'customersCreate',
'isConfigured',
'setSite'
])
->getMock();
$this->mockResponse = $this->getMockBuilder(\RetailCrm\Response\ApiResponse::class)
->disableOriginalConstructor()
->setMethods(['isSuccessful'])
->getMock();
$this->registry = $this->getMockBuilder(\Magento\Framework\Registry::class)
->disableOriginalConstructor()
->getMock();
$this->mockObserver = $this->getMockBuilder(\Magento\Framework\Event\Observer::class)
->disableOriginalConstructor()
->getMock();
$this->mockEvent = $this->getMockBuilder(\Magento\Framework\Event::class)
->disableOriginalConstructor()
->setMethods(['getCustomer'])
->getMock();
$this->mockCustomer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
->disableOriginalConstructor()
->setMethods([
'getStore'
])
->getMock();
$this->mockServiceCustomer = $this->getMockBuilder(\Retailcrm\Retailcrm\Model\Service\Customer::class)
->disableOriginalConstructor()
->getMock();
$this->mockServiceCustomer->expects($this->any())->method('process')->willReturn($this->getCustomerTestData());
$this->helper = $this->createMock(\Retailcrm\Retailcrm\Helper\Data::class);
$this->unit = new \Retailcrm\Retailcrm\Model\Observer\Customer(
$this->registry,
$this->helper,
$this->mockApi,
$this->mockServiceCustomer
);
}
/**
* @param boolean $isSuccessful
* @param boolean $isConfigured
* @dataProvider dataProviderCustomer
*/
public function testExecute(
$isSuccessful,
$isConfigured
) {
// mock Response
$this->mockResponse->expects($this->any())
->method('isSuccessful')
->willReturn($isSuccessful);
$this->mockResponse->errorMsg = 'Not found';
// mock API
$this->mockApi->expects($this->any())
->method('customersEdit')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('customersCreate')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
$store = $this->createMock(\Magento\Store\Model\Store::class);
$this->mockCustomer->expects($this->any())
->method('getStore')
->willReturn($store);
// mock Event
$this->mockEvent->expects($this->any())
->method('getCustomer')
->willReturn($this->mockCustomer);
// mock Observer
$this->mockObserver->expects($this->any())
->method('getEvent')
->willReturn($this->mockEvent);
$customerObserver = $this->unit->execute($this->mockObserver);
if ($isConfigured) {
$this->assertNotEmpty($this->unit->getCustomer());
$this->assertArrayHasKey('externalId', $this->unit->getCustomer());
$this->assertArrayHasKey('email', $this->unit->getCustomer());
$this->assertArrayHasKey('firstName', $this->unit->getCustomer());
$this->assertArrayHasKey('lastName', $this->unit->getCustomer());
$this->assertArrayHasKey('patronymic', $this->unit->getCustomer());
$this->assertArrayHasKey('createdAt', $this->unit->getCustomer());
$this->assertInstanceOf(\Retailcrm\Retailcrm\Model\Observer\Customer::class, $customerObserver);
} else {
$this->assertEmpty($this->unit->getCustomer());
}
}
/**
* @return array
*/
private function getCustomerTestData()
{
return [
'externalId' => 1,
'email' => 'test@mail.com',
'firstName' => 'TestFirstname',
'lastName' => 'Testlastname',
'patronymic' => 'Testmiddlename',
'createdAt' => \date('Y-m-d H:i:s')
];
}
public function dataProviderCustomer()
{
return [
[
'is_successful' => true,
'is_configured' => true
],
[
'is_successful' => false,
'is_configured' => false
],
[
'is_successful' => false,
'is_configured' => true
],
[
'is_successful' => true,
'is_configured' => false
]
];
}
}

View file

@ -0,0 +1,481 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Observer;
use Retailcrm\Retailcrm\Test\TestCase;
/**
* Order create observer test class
*/
class OrderCreateTest extends TestCase
{
private $unit;
private $mockEvent;
private $mockObserver;
private $mockRegistry;
private $mockApi;
private $mockOrder;
private $mockItem;
private $mockStore;
private $mockBillingAddress;
private $mockResponse;
private $mockLogger;
private $mockServiceOrder;
private $mockHelper;
private $mockServiceCustomer;
private $mockCustomer;
public function setUp()
{
$this->mockApi = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods([
'ordersGet',
'ordersCreate',
'customersGet',
'customersCreate',
'customersList',
'getVersion',
'isConfigured',
'setSite'
])
->getMock();
$this->mockObserver = $this->getMockBuilder(\Magento\Framework\Event\Observer::class)
->disableOriginalConstructor()
->getMock();
$this->mockEvent = $this->getMockBuilder(\Magento\Framework\Event::class)
->disableOriginalConstructor()
->setMethods(['getOrder'])
->getMock();
$this->mockLogger = $this->getMockBuilder(\Retailcrm\Retailcrm\Model\Logger\Logger::class)
->disableOriginalConstructor()
->getMock();
$this->mockRegistry = $this->getMockBuilder(\Magento\Framework\Registry::class)
->disableOriginalConstructor()
->getMock();
$this->mockOrder = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
->disableOriginalConstructor()
->setMethods([
'getCustomer',
'getId',
'getBillingAddress',
'getStore'
])
->getMock();
$this->mockStore = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->setMethods(['getCode'])
->getMock();
$this->mockBillingAddress = $this->getMockBuilder(\Magento\Customer\Model\Address\AddressModelInterface::class)
->disableOriginalConstructor()
->setMethods(['getTelephone', 'getData'])
->getMockForAbstractClass();
$this->mockResponse = $this->getMockBuilder(\RetailCrm\Response\ApiResponse::class)
->disableOriginalConstructor()
->setMethods(['isSuccessful'])
->getMock();
$this->mockServiceOrder = $this->getMockBuilder(\Retailcrm\Retailcrm\Model\Service\Order::class)
->disableOriginalConstructor()
->getMock();
$this->mockHelper = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Data::class)
->disableOriginalConstructor()
->getMock();
$this->mockServiceCustomer = $this->getMockBuilder(\Retailcrm\Retailcrm\Model\Service\Customer::class)
->disableOriginalConstructor()
->getMock();
$this->mockServiceCustomer->expects($this->any())->method('process')->willReturn($this->getCustomerTestData());
$this->mockServiceCustomer
->expects($this->any())
->method('prepareCustomerFromOrder')
->willReturn(
$this->getCustomerTestData()
);
$this->mockCustomer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
->disableOriginalConstructor()
->setMethods([
'getId',
'getEmail',
'getFirstname',
'getMiddlename',
'getLastname',
'getStore',
'getGender',
'getDob',
'getDefaultBillingAddress',
'getAddressesCollection'
])
->getMock();
$testData = $this->getAfterSaveCustomerTestData();
// mock Customer
$this->mockCustomer->expects($this->any())
->method('getId')
->willReturn($testData['id']);
$this->mockCustomer->expects($this->any())
->method('getEmail')
->willReturn($testData['email']);
$this->mockCustomer->expects($this->any())
->method('getFirstname')
->willReturn($testData['firstname']);
$this->mockCustomer->expects($this->any())
->method('getMiddlename')
->willReturn($testData['middlename']);
$this->mockCustomer->expects($this->any())
->method('getLastname')
->willReturn($testData['lastname']);
$this->unit = new \Retailcrm\Retailcrm\Model\Observer\OrderCreate(
$this->mockRegistry,
$this->mockLogger,
$this->mockServiceOrder,
$this->mockServiceCustomer,
$this->mockHelper,
$this->mockApi
);
}
/**
* @param boolean $isSuccessful
* @param string $errorMsg
* @param int $customerIsGuest
* @param string $apiVersion
* @param boolean $isConfigured
* @dataProvider dataProviderOrderCreate
*/
public function testExecute(
$isSuccessful,
$errorMsg,
$customerIsGuest,
$apiVersion,
$isConfigured
) {
$testData = $this->getAfterSaveOrderTestData();
// mock Response
$this->mockResponse->expects($this->any())
->method('isSuccessful')
->willReturn($isSuccessful);
$this->mockResponse->errorMsg = $errorMsg;
// mock API
$this->mockApi->expects($this->any())
->method('ordersGet')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('ordersCreate')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('customersGet')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('customersCreate')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('customersList')
->willReturn($this->mockResponse);
$this->mockApi->expects($this->any())
->method('getVersion')
->willReturn($apiVersion);
$this->mockApi->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
// billing address mock set data
$this->mockBillingAddress->expects($this->any())
->method('getTelephone')
->willReturn($testData['order.billingAddress']['telephone']);
$this->mockBillingAddress->expects($this->any())
->method('getData')
->with($this->logicalOr(
$this->equalTo('city'),
$this->equalTo('region'),
$this->equalTo('street'),
$this->equalTo('postcode'),
$this->equalTo('country_id')
))
->will($this->returnCallback([$this, 'getCallbackDataAddress']));
// store mock set data
$this->mockStore->expects($this->any())
->method('getCode')
->willReturn(1);
// order mock set data
$this->mockOrder->expects($this->any())
->method('getId')
->willReturn($testData['order.id']);
$this->mockOrder->expects($this->any())
->method('getBillingAddress')
->willReturn($this->mockBillingAddress);
$this->mockOrder->expects($this->any())
->method('getStore')
->willReturn($this->mockStore);
$this->mockOrder->expects($this->any())
->method('getCustomer')
->willReturn($this->mockCustomer);
// mock Event
$this->mockEvent->expects($this->any())
->method('getOrder')
->willReturn($this->mockOrder);
// mock Observer
$this->mockObserver->expects($this->any())
->method('getEvent')
->willReturn($this->mockEvent);
$this->mockServiceOrder->expects($this->any())->method('process')
->willReturn($this->getOrderTestData($apiVersion, $customerIsGuest));
$orderCreateObserver = $this->unit->execute($this->mockObserver);
if ($isConfigured && !$isSuccessful) {
$this->assertNotEmpty($this->unit->getOrder());
$this->assertArrayHasKey('externalId', $this->unit->getOrder());
$this->assertArrayHasKey('number', $this->unit->getOrder());
$this->assertArrayHasKey('createdAt', $this->unit->getOrder());
$this->assertArrayHasKey('lastName', $this->unit->getOrder());
$this->assertArrayHasKey('firstName', $this->unit->getOrder());
$this->assertArrayHasKey('patronymic', $this->unit->getOrder());
$this->assertArrayHasKey('email', $this->unit->getOrder());
$this->assertArrayHasKey('phone', $this->unit->getOrder());
$this->assertArrayHasKey('status', $this->unit->getOrder());
$this->assertArrayHasKey('items', $this->unit->getOrder());
$this->assertArrayHasKey('delivery', $this->unit->getOrder());
if ($apiVersion == 'v5') {
$this->assertArrayHasKey('payments', $this->unit->getOrder());
} else {
$this->assertArrayHasKey('paymentType', $this->unit->getOrder());
}
$this->assertInstanceOf(\Retailcrm\Retailcrm\Model\Observer\OrderCreate::class, $orderCreateObserver);
} elseif (!$isConfigured || $isSuccessful) {
$this->assertEmpty($this->unit->getOrder());
}
}
private function getOrderTestData($apiVersion, $customerIsGuest)
{
$order = [
'countryIso' => 'RU',
'externalId' => 1,
'number' => '000000001',
'status' => 'new',
'phone' => '890000000000',
'email' => 'test@gmail.com',
'createdAt' => date('Y-m-d H:i:s'),
'lastName' => 'Test',
'firstName' => 'Test',
'patronymic' => 'Tests',
'items' => [
[
'productName' => 'Test product',
'quantity' => 2,
'initialPrice' => 1.000,
'offer' => [
'externalId' => 1
]
]
],
'delivery' => [
'code' => 'test',
'cost' => '100',
'address' => [
'index' => '111111',
'city' => 'Moscow',
'countryIso' => 'RU',
'street' => 'Test street',
'region' => 'Test region',
'text' => '111111, Moscow, Test region, Test street'
]
]
];
if ($apiVersion == 'v5') {
$order['discountManualAmount'] = 0;
$payment = [
'type' => 'test',
'externalId' => 1,
'order' => [
'externalId' => 1,
],
'status' => 'paid'
];
$order['payments'][] = $payment;
} else {
$order['paymentType'] = 'test';
$order['discount'] = 0;
}
if ($customerIsGuest == 0) {
$order['customer']['externalId'] = 1;
}
return $order;
}
/**
* Get test order data
*
* @return array $testOrderData
*/
private function getAfterSaveOrderTestData()
{
$testOrderData = [
'order.id' => 1,
'order.status' => 'processing',
'order.realOrderId' => '000000001',
'order.billingAddress' => [
'telephone' => '890000000000',
'data' => [
'city' => 'Moscow',
'region' => 'Moscow',
'street' => 'TestStreet',
'postcode' => '111111',
'country_id' => 'RU'
]
],
'order.allItems' => [$this->mockItem],
'order.shippingMethod' => 'flatrate_flatrate',
'order.paymentMethod' => 'checkmo',
'order.customerLastname' => 'Test',
'order.customerFirstname' => 'Test',
'order.customerMiddlename' => 'Test',
'order.customerEmail' => 'test@gmail.com'
];
return $testOrderData;
}
public function getCallbackDataAddress($dataKey)
{
$testData = $this->getAfterSaveOrderTestData();
return $testData['order.billingAddress']['data'][$dataKey];
}
public function dataProviderOrderCreate()
{
return [
[
'is_successful' => true,
'error_msg' => 'Not found',
'customer_is_guest' => 1,
'api_version' => 'v4',
'is_configured' => true
],
[
'is_successful' => true,
'error_msg' => 'Not found',
'customer_is_guest' => 0,
'api_version' => 'v4',
'is_configured' => false
],
[
'is_successful' => false,
'error_msg' => 'Not found',
'customer_is_guest' => 1,
'api_version' => 'v4',
'is_configured' => true
],
[
'is_successful' => false,
'error_msg' => 'Not found',
'customer_is_guest' => 0,
'api_version' => 'v4',
'is_configured' => false
],
[
'is_successful' => true,
'error_msg' => 'Not found',
'customer_is_guest' => 1,
'api_version' => 'v5',
'is_configured' => true
],
[
'is_successful' => true,
'error_msg' => 'Not found',
'customer_is_guest' => 0,
'api_version' => 'v5',
'is_configured' => false
],
[
'is_successful' => false,
'error_msg' => 'Not found',
'customer_is_guest' => 1,
'api_version' => 'v5',
'is_configured' => true
],
[
'is_successful' => false,
'error_msg' => 'Not found',
'customer_is_guest' => 0,
'api_version' => 'v5',
'is_configured' => false
]
];
}
/**
* Get test customer data
*
* @return array
*/
private function getAfterSaveCustomerTestData()
{
return [
'id' => 1,
'email' => 'test@mail.com',
'firstname' => 'TestFirstname',
'lastname' => 'Testlastname',
'middlename' => 'Testmiddlename',
'birthday' => '1990-01-01',
'gender' => 1
];
}
/**
* @return array
*/
private function getCustomerTestData()
{
return [
'externalId' => 1,
'email' => 'test@mail.com',
'firstName' => 'TestFirstname',
'lastName' => 'Testlastname',
'patronymic' => 'Testmiddlename',
'createdAt' => \date('Y-m-d H:i:s')
];
}
}

View file

@ -0,0 +1,192 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Observer;
use Retailcrm\Retailcrm\Test\TestCase;
class OrderUpdateTest extends TestCase
{
private $unit;
private $objectManager;
private $config;
private $mockApi;
private $mockObserver;
private $mockEvent;
private $mockOrder;
private $mockPayment;
private $registry;
public function setUp()
{
$this->mockApi = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods([
'ordersEdit',
'ordersPaymentsEdit',
'getVersion',
'isConfigured',
'setSite'
])
->getMock();
$this->mockObserver = $this->getMockBuilder(\Magento\Framework\Event\Observer::class)
->disableOriginalConstructor()
->getMock();
$this->mockEvent = $this->getMockBuilder(\Magento\Framework\Event::class)
->disableOriginalConstructor()
->setMethods(['getOrder'])
->getMock();
$this->objectManager = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class)
->getMockForAbstractClass();
$this->mockOrder = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
->disableOriginalConstructor()
->setMethods([
'getId',
'getPayment',
'getBaseTotalDue',
'getStatus',
'getStore'
])
->getMock();
$this->mockPayment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
->setMethods(['getId'])
->disableOriginalConstructor()
->getMock();
$this->config = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
->getMockForAbstractClass();
$this->registry = $this->getMockBuilder(\Magento\Framework\Registry::class)
->disableOriginalConstructor()
->getMock();
$helper = $this->createMock(\Retailcrm\Retailcrm\Helper\Data::class);
$this->unit = new \Retailcrm\Retailcrm\Model\Observer\OrderUpdate(
$this->config,
$this->registry,
$helper,
$this->mockApi
);
}
/**
* @param int $getBaseTotalDue
* @param string $apiVersion
* @param boolean $isConfigured
* @dataProvider dataProviderOrderUpdate
*/
public function testExecute(
$getBaseTotalDue,
$apiVersion,
$isConfigured
) {
$testData = $this->getAfterUpdateOrderTestData();
// mock Payment
$this->mockPayment->expects($this->any())
->method('getId')
->willReturn(1);
// mock Order
$this->mockOrder->expects($this->any())
->method('getId')
->willReturn($testData['order.id']);
$this->mockOrder->expects($this->any())
->method('getStatus')
->willReturn($testData['order.status']);
$this->mockOrder->expects($this->any())
->method('getBaseTotalDue')
->willReturn($getBaseTotalDue);
$this->mockOrder->expects($this->any())
->method('getPayment')
->willReturn($this->mockPayment);
$store = $this->createMock(\Magento\Store\Model\Store::class);
$this->mockOrder->expects($this->any())
->method('getStore')
->willReturn($store);
// mock Api
$this->mockApi->expects($this->any())
->method('getVersion')
->willReturn($apiVersion);
$this->mockApi->expects($this->any())
->method('isConfigured')
->willReturn($isConfigured);
// mock Event
$this->mockEvent->expects($this->any())
->method('getOrder')
->willReturn($this->mockOrder);
// mock Observer
$this->mockObserver->expects($this->any())
->method('getEvent')
->willReturn($this->mockEvent);
$updateOrderObserver = $this->unit->execute($this->mockObserver);
if ($isConfigured) {
$this->assertNotEmpty($this->unit->getOrder());
$this->assertArrayHasKey('externalId', $this->unit->getOrder());
$this->assertArrayHasKey('status', $this->unit->getOrder());
$this->assertInstanceOf(
\Retailcrm\Retailcrm\Model\Observer\OrderUpdate::class,
$updateOrderObserver
);
} else {
$this->assertEmpty($this->unit->getOrder());
}
}
/**
* Get test order data
* @return array $testOrderData
*/
private function getAfterUpdateOrderTestData()
{
$testOrderData = [
'order.id' => 1,
'order.status' => 'processing',
'order.paymentMethod' => 'checkmo'
];
return $testOrderData;
}
public function dataProviderOrderUpdate()
{
return [
[
'get_base_total_due' => 0,
'api_version' => 'v4',
'is_configured' => false
],
[
'get_base_total_due' => 1,
'api_version' => 'v4',
'is_configured' => true
],
[
'get_base_total_due' => 0,
'api_version' => 'v5',
'is_configured' => true
],
[
'get_base_total_due' => 1,
'api_version' => 'v5',
'is_configured' => false
]
];
}
}

View file

@ -0,0 +1,244 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Model\Service;
use Retailcrm\Retailcrm\Test\TestCase;
class CustomerTest extends TestCase
{
private $mockData;
private $mockCustomer;
private $unit;
private $mockOrder;
private $mockBillingAddress;
public function setUp()
{
$this->mockData = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Data::class)
->disableOriginalConstructor()
->getMock();
$this->mockCustomer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
->disableOriginalConstructor()
->setMethods([
'getId',
'getEmail',
'getFirstname',
'getMiddlename',
'getLastname',
'getStore',
'getGender',
'getDob',
'getDefaultBillingAddress',
'getAddressesCollection'
])
->getMock();
$this->mockOrder = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
->disableOriginalConstructor()
->setMethods([
'getBillingAddress',
])
->getMock();
$this->mockBillingAddress = $this->getMockBuilder(\Magento\Customer\Model\Address\AddressModelInterface::class)
->disableOriginalConstructor()
->setMethods([
'getTelephone',
'getEmail',
'getData',
'getFirstname',
'getMiddlename',
'getLastname',
'getCountryId',
'getPostcode',
'getRegion',
'getCity',
'getStreet'
])
->getMockForAbstractClass();
$this->unit = new \Retailcrm\Retailcrm\Model\Service\Customer(
$this->mockData
);
}
public function testPrepareCustomerFromOrder()
{
$this->mockOrder->expects($this->any())
->method('getBillingAddress')
->willReturn($this->mockBillingAddress);
$result = $this->unit->prepareCustomerFromOrder($this->mockOrder);
$this->assertNotEmpty($result);
$this->assertInternalType('array', $result);
$this->assertArrayNotHasKey('externalId', $result);
$this->assertArrayHasKey('email', $result);
$this->assertArrayHasKey('firstName', $result);
$this->assertArrayHasKey('lastName', $result);
$this->assertArrayHasKey('patronymic', $result);
$this->assertArrayHasKey('address', $result);
$this->assertInternalType('array', $result['address']);
$this->assertArrayHasKey('countryIso', $result['address']);
$this->assertArrayHasKey('index', $result['address']);
$this->assertArrayHasKey('region', $result['address']);
$this->assertArrayHasKey('city', $result['address']);
$this->assertArrayHasKey('street', $result['address']);
$this->assertArrayHasKey('text', $result['address']);
}
/**
* @param $apiVersion
*
* @dataProvider dataProvider
*/
public function testProcess($apiVersion)
{
$mockAddress = $this->getMockBuilder(\Magento\Customer\Model\Address::class)
->disableOriginalConstructor()
->setMethods([
'getData',
'getTelephone'
])
->getMock();
$mockAddress->expects($this->any())
->method('getData')
->with(
$this->logicalOr(
$this->equalTo('postcode'),
$this->equalTo('country_id'),
$this->equalTo('region'),
$this->equalTo('city'),
$this->equalTo('street')
)
)
->will($this->returnCallback([$this, 'getCallbackDataAddress']));
$mockAddress->expects($this->any())
->method('getTelephone')
->willReturn('000-00-00');
$this->mockData->expects($this->any())
->method('getGeneralSettings')
->with('api_version')
->willReturn($apiVersion);
$testData = $this->getAfterSaveCustomerTestData();
// mock Customer
$this->mockCustomer->expects($this->any())
->method('getId')
->willReturn($testData['id']);
$this->mockCustomer->expects($this->any())
->method('getEmail')
->willReturn($testData['email']);
$this->mockCustomer->expects($this->any())
->method('getFirstname')
->willReturn($testData['firstname']);
$this->mockCustomer->expects($this->any())
->method('getMiddlename')
->willReturn($testData['middlename']);
$this->mockCustomer->expects($this->any())
->method('getLastname')
->willReturn($testData['lastname']);
$this->mockCustomer->expects($this->any())
->method('getGender')
->willReturn($testData['gender']);
$this->mockCustomer->expects($this->any())
->method('getDob')
->willReturn($testData['birthday']);
$this->mockCustomer->expects($this->any())
->method('getDefaultBillingAddress')
->willReturn($mockAddress);
$this->mockCustomer->expects($this->any())
->method('getAddressesCollection')
->willReturn([$mockAddress]);
$result = $this->unit->process($this->mockCustomer);
$this->assertNotEmpty($result);
$this->assertInternalType('array', $result);
$this->assertArrayHasKey('externalId', $result);
$this->assertNotEmpty($result['externalId']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['id'], $result['externalId']);
$this->assertArrayHasKey('email', $result);
$this->assertNotEmpty($result['email']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['email'], $result['email']);
$this->assertArrayHasKey('firstName', $result);
$this->assertNotEmpty($result['firstName']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['firstname'], $result['firstName']);
$this->assertArrayHasKey('lastName', $result);
$this->assertNotEmpty($result['lastName']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['lastname'], $result['lastName']);
$this->assertArrayHasKey('patronymic', $result);
$this->assertNotEmpty($result['patronymic']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['middlename'], $result['patronymic']);
if ($apiVersion == 'v5') {
$this->assertArrayHasKey('birthday', $result);
$this->assertNotEmpty($result['birthday']);
$this->assertEquals($this->getAfterSaveCustomerTestData()['birthday'], $result['birthday']);
$this->assertArrayHasKey('sex', $result);
$this->assertNotEmpty($result['sex']);
$this->assertEquals('male', $result['sex']);
}
}
public function getCallbackDataAddress($dataKey)
{
$address = [
'postcode' => 'test-index',
'country_id' => 'US',
'region' => 'test-region',
'city' => 'test-city',
'street' => 'test-street'
];
return $address[$dataKey];
}
/**
* Get test customer data
*
* @return array
*/
private function getAfterSaveCustomerTestData()
{
return [
'id' => 1,
'email' => 'test@mail.com',
'firstname' => 'TestFirstname',
'lastname' => 'Testlastname',
'middlename' => 'Testmiddlename',
'birthday' => '1990-01-01',
'gender' => 1
];
}
/**
* Data provider
*
* @return array
*/
public function dataProvider()
{
return [
[
'api_version' => 'v4',
],
[
'api_version' => 'v5'
]
];
}
}

View file

@ -0,0 +1,147 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Model\Service;
use Retailcrm\Retailcrm\Test\TestCase;
class IntegrationModuleTest extends TestCase
{
private $mockResourceConfig;
private $mockApiClient;
private $mockData;
private $unit;
const ACCOUNT_URL = 'test';
public function setUp()
{
$this->mockData = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Data::class)
->disableOriginalConstructor()
->getMock();
$this->mockResourceConfig = $this->getMockBuilder(\Magento\Config\Model\ResourceModel\Config::class)
->disableOriginalConstructor()
->getMock();
$this->mockApiClient = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods([
'marketplaceSettingsEdit',
'integrationModulesEdit'
])
->getMock();
$this->unit = new \Retailcrm\Retailcrm\Model\Service\IntegrationModule(
$this->mockResourceConfig,
$this->mockData
);
}
/**
* @param $active
* @param $apiVersion
* @param $isSuccessful
*
* @dataProvider dataProvider
*/
public function testSendConfiguration($active, $apiVersion, $isSuccessful)
{
$response = $this->getMockBuilder(\RetailCrm\Response\ApiResponse::class)
->disableOriginalConstructor()
->getMock();
$response->expects($this->any())->method('isSuccessful')->willReturn($isSuccessful);
if ($apiVersion == 'v4') {
$this->mockApiClient->expects($this->any())->method('marketplaceSettingsEdit')
->willReturn($response);
} else {
$this->mockApiClient->expects($this->any())->method('integrationModulesEdit')
->willReturn($response);
}
$this->unit->setAccountUrl(self::ACCOUNT_URL);
$this->unit->setApiVersion($apiVersion);
$this->unit->sendConfiguration($this->mockApiClient, $active);
$configuration = $this->unit->getConfiguration();
$this->assertNotEmpty($configuration);
$this->assertArrayHasKey('name', $configuration);
$this->assertEquals(
\Retailcrm\Retailcrm\Model\Service\IntegrationModule::NAME,
$configuration['name']
);
$this->assertArrayHasKey('logo', $configuration);
$this->assertEquals(
\Retailcrm\Retailcrm\Model\Service\IntegrationModule::LOGO,
$configuration['logo']
);
$this->assertArrayHasKey('code', $configuration);
$this->assertContains(
\Retailcrm\Retailcrm\Model\Service\IntegrationModule::INTEGRATION_CODE,
$configuration['code']
);
$this->assertArrayHasKey('active', $configuration);
$this->assertEquals($active, $configuration['active']);
if ($apiVersion == 'v4') {
$this->assertArrayHasKey('configurationUrl', $configuration);
$this->assertEquals(self::ACCOUNT_URL, $configuration['configurationUrl']);
} else {
$this->assertArrayHasKey('accountUrl', $configuration);
$this->assertEquals(self::ACCOUNT_URL, $configuration['accountUrl']);
$this->assertArrayHasKey('integrationCode', $configuration);
$this->assertContains(
\Retailcrm\Retailcrm\Model\Service\IntegrationModule::INTEGRATION_CODE,
$configuration['integrationCode']
);
$this->assertArrayHasKey('clientId', $configuration);
$this->assertNotEmpty($configuration['clientId']);
}
}
public function dataProvider()
{
return [
[
'active' => true,
'api_version' => 'v4',
'is_successful' => true
],
[
'active' => false,
'api_version' => 'v4',
'is_successful' => true
],
[
'active' => true,
'api_version' => 'v4',
'is_successful' => false
],
[
'active' => false,
'api_version' => 'v4',
'is_successful' => false
],
[
'active' => true,
'api_version' => 'v5',
'is_successful' => true
],
[
'active' => false,
'api_version' => 'v5',
'is_successful' => true
],
[
'active' => true,
'api_version' => 'v5',
'is_successful' => false
],
[
'active' => false,
'api_version' => 'v5',
'is_successful' => false
]
];
}
}

View file

@ -0,0 +1,126 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Model\Service;
use Retailcrm\Retailcrm\Test\TestCase;
class InventoriesUploadTest extends TestCase
{
private $mockApi;
private $mockProductRepository;
private $mockResponse;
private $mockProduct;
public function setUp()
{
$this->mockApi = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class)
->disableOriginalConstructor()
->setMethods([
'storeInventories',
'isConfigured'
])
->getMock();
$this->mockProductRepository = $this->getMockBuilder(\Magento\Catalog\Api\ProductRepositoryInterface::class)
->disableOriginalConstructor()
->setMethods(['getById'])
->getMockForAbstractClass();
$this->mockResponse = $this->getMockBuilder(\RetailCrm\Response\ApiResponse::class)
->disableOriginalConstructor()
->setMethods(['isSuccessful'])
->getMock();
$this->mockProduct = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
->disableOriginalConstructor()
->setMethods([
'setStockData',
'save'
])
->getMock();
}
/**
* @param $response
*
* @dataProvider dataProviderLoadStocks
*/
public function testInventoriesUpdload($response)
{
if ($response != false) {
$responseInventories = new \RetailCrm\Response\ApiResponse(200, json_encode($response));
$responseInventories->asJsonResponse($response);
$this->mockResponse->expects($this->any())
->method('isSuccessful')
->willReturn(true);
$this->mockApi->expects($this->any())
->method('isConfigured')
->willReturn(true);
$this->mockApi->expects($this->any())
->method('storeInventories')
->willReturn($responseInventories);
$this->mockProductRepository->expects($this->any())
->method('getById')
->willReturn($this->mockProduct);
} else {
$this->mockResponse->expects($this->any())
->method('isSuccessful')
->willReturn($response);
}
$inventoriesUpload = new \Retailcrm\Retailcrm\Model\Service\InventoriesUpload($this->mockProductRepository, $this->mockApi);
$result = $inventoriesUpload->uploadInventory();
if (!$response['success']) {
$this->assertEquals(false, $result);
} else {
$this->assertEquals(true, $result);
}
}
private function getResponseData()
{
return array(
'true' => $this->getApiInventories(),
'false' => false
);
}
public function dataProviderLoadStocks()
{
$response = $this->getResponseData();
return array(
array(
'response' => $response['true']
),
array(
'response' => $response['false']
)
);
}
private function getApiInventories()
{
return array(
'success' => true,
'pagination' => array(
'limit' => 250,
'totalCount' => 1,
'currentPage' => 1,
'totalPageCount' => 1
),
'offers' => array(
array(
'externalId' => 1,
'xmlId' => 'xmlId',
'quantity' => 10
)
)
);
}
}

View file

@ -0,0 +1,236 @@
<?php
namespace Retailcrm\Retailcrm\Test\Unit\Model\Service;
use Retailcrm\Retailcrm\Test\TestCase;
class OrderTest extends TestCase
{
private $mockProductRepository;
private $mockHelper;
private $mockConfig;
private $mockConfigurableProduct;
private $mockOrder;
private $unit;
public function setUp()
{
$this->mockProductRepository = $this->getMockBuilder(\Magento\Catalog\Model\ProductRepository::class)
->disableOriginalConstructor()
->getMock();
$this->mockConfigurableProduct = $this->getMockBuilder(
\Magento\ConfigurableProduct\Model\Product\Type\Configurable::class
)->disableOriginalConstructor()->getMock();
$this->mockHelper = $this->createMock(\Retailcrm\Retailcrm\Helper\Data::class);
$this->mockConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
->getMockForAbstractClass();
$this->mockOrder = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
->disableOriginalConstructor()
->getMock();
$this->unit = new \Retailcrm\Retailcrm\Model\Service\Order(
$this->mockProductRepository,
$this->mockConfig,
$this->mockConfigurableProduct,
$this->mockHelper
);
}
/**
* @dataProvider dataProvider
*
* @param $productType
* @param $customerIsGuest
* @param $apiVersion
*/
public function testProcess($productType, $customerIsGuest, $apiVersion)
{
$this->mockHelper->expects($this->any())->method('getGeneralSettings')
->with('api_version')->willReturn($apiVersion);
$this->mockHelper->expects($this->any())->method('getConfigPayments')->willReturn(['checkmo'=>'test']);
$this->mockHelper->expects($this->any())->method('getCongigStatus')->willReturn(['processing'=>'test']);
$this->mockHelper->expects($this->any())->method('getCongigShipping')->willReturn(['flatrate'=>'test']);
$this->mockConfig->expects($this->any())->method('getValue')
->with($this->logicalOr(
$this->equalTo('retailcrm/retailcrm_site/default')
))->will($this->returnCallback([$this, 'getCallbackDataConfig']));
$mockProduct = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
->disableOriginalConstructor()
->getMock();
$mockProduct->expects($this->any())->method('getId')->willReturn(1);
$mockItem = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
->disableOriginalConstructor()
->getMock();
$mockItem->expects($this->any())->method('getProductType')->willReturn($productType);
$mockItem->expects($this->any())->method('getProductOptions')
->willReturn([
'attributes_info' => [
[
'option_id' => 1,
'option_value' => 1
]
]
]);
$mockItem->expects($this->any())->method('getProduct')->willReturn($mockProduct);
$mockItem->expects($this->any())->method('getPrice')->willReturn(100.000);
$mockItem->expects($this->any())->method('getName')->willReturn('Test product');
$mockItem->expects($this->any())->method('getQtyOrdered')->willReturn(2);
$mockConfigurableProduct = $this->getMockBuilder(
\Magento\ConfigurableProduct\Model\Product\Type\Configurable::class
)
->disableOriginalConstructor()
->getMock();
$mockConfigurableProduct->expects($this->any())->method('getProductByAttributes')->willReturn($mockProduct);
$mockShippingAddress = $this->getMockBuilder(\Magento\Sales\Model\Order\Address::class)
->disableOriginalConstructor()
->setMethods([
'getData',
'getTelephone',
'getFirstname',
'getLastname',
'getMiddlename',
'getEmail'
])
->getMock();
$mockShippingAddress->expects($this->any())
->method('getData')
->with($this->logicalOr(
$this->equalTo('city'),
$this->equalTo('region'),
$this->equalTo('street'),
$this->equalTo('postcode'),
$this->equalTo('country_id')
))
->will($this->returnCallback([$this, 'getCallbackDataAddress']));
$mockShippingAddress->expects($this->any())->method('getTelephone')->willReturn('89000000000');
$mockShippingAddress->expects($this->any())->method('getFirstname')->willReturn('Test');
$mockShippingAddress->expects($this->any())->method('getLastname')->willReturn('Test');
$mockShippingAddress->expects($this->any())->method('getMiddlename')->willReturn('Test');
$mockShippingAddress->expects($this->any())->method('getEmail')->willReturn('test@mail.com');
$mockPaymentMethod = $this->getMockBuilder(\Magento\Payment\Model\MethodInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$mockPaymentMethod->expects($this->any())->method('getCode')->willReturn('checkmo');
$mockPayment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
->setMethods(['getMethodInstance'])
->disableOriginalConstructor()
->getMock();
$mockPayment->expects($this->any())->method('getMethodInstance')->willReturn($mockPaymentMethod);
$this->mockOrder->expects($this->any())->method('getAllItems')->willReturn([$mockItem]);
$this->mockOrder->expects($this->any())->method('getShippingAddress')->willReturn($mockShippingAddress);
$this->mockOrder->expects($this->any())->method('getShippingMethod')->willReturn('flatrate_flatrate');
$this->mockOrder->expects($this->any())->method('getId')->willReturn(1);
$this->mockOrder->expects($this->any())->method('getRealOrderId')->willReturn('000000001');
$this->mockOrder->expects($this->any())->method('getCreatedAt')->willReturn(date('Y-m-d H:i:s'));
$this->mockOrder->expects($this->any())->method('getStatus')->willReturn('processing');
$this->mockOrder->expects($this->any())->method('getShippingAmount')->willReturn(100);
$this->mockOrder->expects($this->any())->method('getDiscountAmount')->willReturn(0);
$this->mockOrder->expects($this->any())->method('getPayment')->willReturn($mockPayment);
$this->mockOrder->expects($this->any())->method('getBaseTotalDue')->willReturn(0);
$this->mockOrder->expects($this->any())->method('getCustomerIsGuest')->willReturn($customerIsGuest);
$this->mockOrder->expects($this->any())->method('getCustomerId')->willReturn(1);
$resultOrder = $this->unit->process($this->mockOrder);
$this->assertNotEmpty($resultOrder);
$this->assertArrayHasKey('externalId', $resultOrder);
$this->assertArrayHasKey('number', $resultOrder);
$this->assertArrayHasKey('createdAt', $resultOrder);
$this->assertArrayHasKey('lastName', $resultOrder);
$this->assertArrayHasKey('firstName', $resultOrder);
$this->assertArrayHasKey('patronymic', $resultOrder);
$this->assertArrayHasKey('email', $resultOrder);
$this->assertArrayHasKey('phone', $resultOrder);
$this->assertArrayHasKey('items', $resultOrder);
$this->assertArrayHasKey('delivery', $resultOrder);
if ($apiVersion == 'v5') {
$this->assertArrayHasKey('payments', $resultOrder);
} else {
$this->assertArrayHasKey('paymentType', $resultOrder);
}
}
public function getCallbackDataConfig($key)
{
$data = [
'retailcrm/retailcrm_site/default' => 'test'
];
return $data[$key];
}
public function dataProvider()
{
return [
[
'product_type' => 'simple',
'customer_is_guest' => 1,
'api_version' => 'v4'
],
[
'product_type' => 'configurable',
'customer_is_guest' => 1,
'api_version' => 'v4'
],
[
'product_type' => 'simple',
'customer_is_guest' => 0,
'api_version' => 'v4'
],
[
'product_type' => 'configurable',
'customer_is_guest' => 0,
'api_version' => 'v4'
],
[
'product_type' => 'simple',
'customer_is_guest' => 1,
'api_version' => 'v5'
],
[
'product_type' => 'configurable',
'customer_is_guest' => 1,
'api_version' => 'v5'
],
[
'product_type' => 'simple',
'customer_is_guest' => 0,
'api_version' => 'v5'
],
[
'product_type' => 'configurable',
'customer_is_guest' => 0,
'api_version' => 'v5'
]
];
}
public function getCallbackDataAddress($dataKey)
{
$address = [
'city' => 'Moscow',
'region' => 'Moscow',
'street' => 'Test street',
'postcode' => '111111',
'country_id' => 'RU'
];
return $address[$dataKey];
}
}

29
src/composer.json Normal file
View file

@ -0,0 +1,29 @@
{
"name": "retailcrm/retailcrm",
"description": "RetailCRM",
"require": {
"retailcrm/api-client-php": "~5.0"
},
"type": "magento2-module",
"version": "2.5.2",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"authors": [
{
"name": "RetailDriver LLC",
"email": "integration@retailcrm.ru",
"homepage": "https://www.retailcrm.ru",
"role": "Developer"
}
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Retailcrm\\Retailcrm\\": ""
}
}
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
</menu>
</config>

View file

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="retailcrm_retailcrm" frontName="retailcrm_retailcrm">
<module name="Retailcrm_Retailcrm" before="Magento_Backend" />
</route>
</router>
</config>

View file

@ -0,0 +1,98 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<tab id="retailcrm" translate="label" sortOrder="10">
<label>RetailCRM</label>
</tab>
<section id="retailcrm" translate="label" sortOrder="130" showInDefault="1" showInWebsite="1" showInStore="1">
<class>separator-top</class>
<label>Settings</label>
<tab>retailcrm</tab>
<resource>Retailcrm_Retailcrm::retailcrm_configuration</resource>
<group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Main settings</label>
<field id="api_url" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>API URL</label>
<comment>https://YourCrmName.retailcrm.ru</comment>
<backend_model>Retailcrm\Retailcrm\Model\Config\Backend\ApiUrl</backend_model>
</field>
<field id="api_key" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
<label>API key</label>
<comment>You can create an API key in the administration section of RetailCRM</comment>
</field>
<field id="api_version" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>API version</label>
<source_model>Retailcrm\Retailcrm\Model\Setting\ApiVersions</source_model>
<backend_model>Retailcrm\Retailcrm\Model\Config\Backend\ApiVersion</backend_model>
</field>
</group>
<group id="catalog" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Catalogue settings</label>
<field id="attributes_to_export_into_icml" translate="label" type="multiselect" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Attributes for uploading to ICML</label>
<comment>Select attributes which will be uploaded to ICML</comment>
<source_model>Retailcrm\Retailcrm\Model\Setting\Attribute</source_model>
</field>
</group>
<group id="shippingList" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Delivery types</label>
<field id="shippingList" translate="label" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
<label>shipping settings</label>
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\ShippingList</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
</field>
</group>
<group id="paymentList" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Payment types</label>
<field id="paymentList" translate="label" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
<label>payment settings</label>
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\PaymentList</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
</field>
</group>
<group id="statusList" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Status types</label>
<field id="statusList" translate="label" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
<label>status settings</label>
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\StatusList</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
</field>
</group>
<group id="load" translate="label" type="text" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Uploading orders</label>
<field id="number_order" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Order number</label>
<comment>Enter order numbers separated by a comma for uploading</comment>
</field>
<field id="button_order" translate="label comment" type="button" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Button</frontend_model>
</field>
</group>
<group id="site" translate="label" type="select" sortOrder="60" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Setting the store by default</label>
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Site</frontend_model>
</group>
<group id="sites" translate="label" type="select" sortOrder="70" showInDefault="0" showInWebsite="1" showInStore="0">
<label>Setting the stores correspondence</label>
<frontend_model>Retailcrm\Retailcrm\Block\Adminhtml\System\Config\Form\Fieldset\Sites</frontend_model>
</group>
<group id="daemon_collector" translate="label" type="select" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Daemon Collector</label>
<field id="active" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Activate</label>
<source_model>Retailcrm\Retailcrm\Model\Setting\Select</source_model>
</field>
<field id="key" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Site key</label>
</field>
</group>
<group id="inventories_upload" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Synchronization of the stock balance</label>
<field id="active" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Activate</label>
<source_model>Retailcrm\Retailcrm\Model\Setting\Select</source_model>
</field>
</group>
</section>
</system>
</config>

15
src/etc/config.xml Normal file
View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<retailcrm>
<general>
<api_url>test</api_url>
</general>
<section>
<general>
<api_key>{value}</api_key>
</general>
</section>
</retailcrm>
</default>
</config>

14
src/etc/crontab.xml Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job name="create_icml" instance="Retailcrm\Retailcrm\Cron\Icml" method="execute">
<schedule>* */4 * * *</schedule>
</job>
<job name="order_hystory" instance="Retailcrm\Retailcrm\Cron\OrderHistory" method="execute">
<schedule>*/5 * * * *</schedule>
</job>
<job name="inventories" instance="Retailcrm\Retailcrm\Cron\Inventories" method="execute">
<schedule>*/15 * * * *</schedule>
</job>
</group>
</config>

20
src/etc/di.xml Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Retailcrm\Retailcrm\Helper\Proxy">
<arguments>
<argument name="pathUrl" xsi:type="const">Retailcrm\Retailcrm\Api\ConfigManagerInterface::URL_PATH</argument>
<argument name="pathKey" xsi:type="const">Retailcrm\Retailcrm\Api\ConfigManagerInterface::KEY_PATH</argument>
<argument name="pathVersion" xsi:type="const">Retailcrm\Retailcrm\Api\ConfigManagerInterface::API_VERSION_PATH</argument>
</arguments>
</type>
<type name="Magento\Framework\Console\CommandList">
<arguments>
<argument name="commands" xsi:type="array">
<item name="orders_export_command" xsi:type="object">Retailcrm\Retailcrm\Console\Command\OrdersExport</item>
<item name="customers_export_command" xsi:type="object">Retailcrm\Retailcrm\Console\Command\CustomersExport</item>
<item name="icml_generate_command" xsi:type="object">Retailcrm\Retailcrm\Console\Command\IcmlGenerate</item>
</argument>
</arguments>
</type>
</config>

Some files were not shown because too many files have changed in this diff Show more