An open API service indexing awesome lists of open source software.

https://github.com/dapi/moysklad

Правильный Ruby-клиент для работы c REST XML API moyslad.ru
https://github.com/dapi/moysklad

Last synced: about 1 year ago
JSON representation

Правильный Ruby-клиент для работы c REST XML API moyslad.ru

Awesome Lists containing this project

README

          

# Ruby-клиент для REST XML API Moysklad

[![Build Status](https://travis-ci.org/BrandyMint/moysklad.svg)](https://travis-ci.org/dapi/moysklad)
[![Dependency Status](https://www.versioneye.com/user/projects/548225818674a4b5b90004dd/badge.svg?style=flat)](https://www.versioneye.com/user/projects/548225818674a4b5b90004dd)
[![Code Climate](https://codeclimate.com/github/dapi/moysklad/badges/gpa.svg)](https://codeclimate.com/github/dapi/moysklad)

* http://www.rubydoc.info/gems/moysklad

## Особенности

* Модуль разработан согласно принципам SOLID. Легко расширяем.
* Все используемые сущности описаны и структурированы. Например [Good](lib/moysklad/entities/good.rb)
* Любые действия с ресурсами (Create, Read, Update, Delete, List).
* Виртуальные действия с ресурсами (`where`, `findWhere`)
* Автоматическая подгрузка списка если все данные не уместились в один запрос (метод `all`)
* _Кеширование и предзагрузка_ ресурса со всеми записями (используем ресурс как локальную базу)
* Работа с нескольмими аккаунтами склада одновременно (отсуствие глобальных переменных).
* Удобная работа с подресурсами (например справочником свойств товара)
* _Ассоциации_ между сущностями автоматически получают данные по API (`good.features`).
* [Client](lib/moysklad/client.rb) для прямого обращения к API в случае крайней необходимости.

## Установка

Все, как обычно, добавляем в Gemfile:

gem 'moysklad'

## Использование

Создаем благоприятное окружение для работы с API:

```ruby
universe = Moysklad::Universe.build login:'ВАШ ЛОГИН', password:'ВАШ ПАРОЛЬ'
```

### Список элементов.

Например список товаров (`Good`).

```ruby
universe.goods.list
# => [Moysklad::Entities::Good, Moysklad::Entities::Good, ..]
```

Обратите внимание, что список возвращается "как есть" и для работы с ним есть более удобные методы.

Параметры списка.

```ruby
universe.stock.list slotUuid: uuid
```

Страница товаров:

```ruby
page = universe.goods.page
# => Moysklad::Entities::Page

page.total
# => 1280

page.count
# => 1000

page.start
# => 0

# page.items
# =>[Moysklad::Entities::Good, ..]

Есть очень удобная возможность автоматически загрузать ВСЕ товары с учетом пейджирования:

> goods = universe.goods.all
> goods.count
> => 1280

> goods
> => [Moysklad::Entities::Page]
```

### Получить конкретный элемент

```ruby
universe.goods.get $uuid
# => [Moysklad::Entities::Good]
```

### Создаем элемент

Например загрузка заказа покупателя:

```ruby
co = Moysklad::Entities::CustomerOrder.new
co.vatIncluded = true
co.applicable = true
[...]
co.customerOrderPosition = [Moysklad::Entities::CustomerOrderPosition.new]

created_order = universe.customer_orders.create co
# => [Moysklad::Entities::Good]

created_order.uuid
# => uuid нового заказа
```

### Удаляем элемент

```ruby
universe.goods.delete $uuid
```

### Кеширование и предзагрузка

Одной из главных возможностей данного модуля является возможность работать с API как с базой данных,
не выполняя запрос по получению каждого товара по-отдельности, и выдавать данные их кеша.

Класический способ получить данные по товару делает GET запрос каждый раз:

```ruby
universe.goods.get $uuid
# => Client: GET exchange/rest/ms/xml/Good/f24937e7-7ba1-11e4-90a2-8ecb000abf12 {}
# => [Moysklad::Entities::Good]
```

Продвинутый способ вытаскивает все данные сразу и в дальнейшем берет обьекты из кеша:

```ruby
> universe.goods.find $uuid
# => Client: GET exchange/rest/ms/xml/Good/list {:start=>0}
# => Client: GET exchange/rest/ms/xml/Good/list {:start=>1000}
# => [Moysklad::Entities::Good]
```

И в следующий раз API уже не дергается:

```ruby
universe.goods.find $another_uuid
# => [Moysklad::Entities::Good]
```

Это позволяет экономить на прямых запросах к API и избавляет нас от блокирования моимскладом по ограничению количества запросов за еденицу времени.

## Поиск по фильтру

Возвращает список элементов отображенных по фильтру:

```ruby
universe.features.where goodUuid: uuid
# => [Moysklad::Enities::Feature, Moysklad::Enities::Feature]
```

Тоже самое, только возвращается первый элемент или nil:

```ruby
universe.features.findWhere goodUuid: uuid
# => [Moysklad::Enities::Feature]
```

### Список доступных ресурсов:

```ruby
universe.resources_list
# => [:stock, :embedded_entity_metadata, :custom_entity_metadata, :goods, :good_folders, :uoms, :countries,
:features, :custom_entities, :customer_orders, :warehouses, :companies,
:consignments, :my_companies]
```

## Справочники и подресурсы

Доступ к Мойсклад устроен так, что некоторые справочники запрятаны в одной коллекции.
Например если вы хотите получить все виды свойств товаров, то это можно сделать следующим образом.

```ruby
universe.embedded_entity_metadata.subresource_by_name(:GoodFolder).all
# => [Moysklad::Entities::AttributeMetadata, Moysklad::Entities::AttributeMetadata]
```

Или получить конкретное свойство:

```ruby
universe.embedded_entity_metadata.subresource_by_name(:GoodFolder).find uuid
# => Moysklad::Entities::AttributeMetadata
```

## Автоматическая обработка ассоциаций (отношения)

Нравятся `belongs_to` и `has_many` в рельсах? Тут есть почти тоже самое.

```ruby
feature = universe.features.find uuid
feature.good
# Client: GET exchange/rest/ms/xml/Good/f24937e7-7ba1-11e4-90a2-8ecb000abf12 {}
# => [Moysklad::Entities::Good]
```

Пример как получить все данные по товару, включая модификации, свойства и их характеристики:

```ruby
good = universe.goods.find uuid
# Client: GET exchange/rest/ms/xml/Good/f24937e7-7ba1-11e4-90a2-8ecb000abf12 {}

good.features universe
# Client: GET exchange/rest/ms/xml/Feature/list {}
# => [Moysklad::Entities::Feature, ..]

attribute = good.attributes.first
# => [Moysklad::Entities::Attribute, ..]

attribute.is_dictionary?
# => true
```

Получаем вид свойства:

```ruby
attribute.embedded_entity_metadata universe
# Client: GET exchange/rest/ms/xml/Metadata/list {}
# => [Moysklad::Entities::AttributeMetadata]
```

Получаем описание пользовательского справочника к которому принадлежит свойства

```ruby
dictionary = attribute.embedded_entity_metadata(universe).dictionatyMetadata(universe)
# Client: GET exchange/rest/ms/xml/CustomEntityMetadata/uuid {}
# => [Moysklad::Entities::CustomEntityMetadata]
```

Значения всех элементов пользовательского справочника:

```ruby
dictionary.entities(universe)
# => [Moysklad::Entities::CustomEntity, ...]
```

Подробнее смотри в исходниках сущностей.

## Pull Requests

### Добавление новых моделей и ресурсов.

На данный момен в библиотеку добавлено 60% справочников используемых в моемскладе. Я добавляю новые справочники по мере необходимости. Но вы можете это сделать и сами следующим образом.

Например добавляем `Country`.

1. Добавляем в фикстуры пример выгрузки из API для тестирования и отладки:

MS_LOGON=логин MS_PASSWORD=пароль ./scripts/rest.sh Country list > ./spec/fixtures/Country_list.raw

2. Создаем сущность на основе уже существующей, например good.rb

cp ./lib/moysklad/entities/good.rb ./lib/moysklad/entities/country.rb

3. Описываем свойства новой сущности Country.rb в терминах [nokogiri-happymapper](https://github.com/dam5s/happymapper)-а

vi ./lib/moysklad/entities/country.rb

4. Добавляем сущность в requirements

vi ./lib/moysklad/entities.rb

5. Содаем автоматический ресурс (имя ресурса во множественном числе)

vi ./lib/moysklad/resources.rb

6. Делаем spec для сущности и для ресурса.

> vi ./spec/lib/moysklad/resources/countries_spec.rb
> vi ./spec/lib/moysklad/entities/country_spec.rb

7. Проверяем что тесты проходят.

8. Присылаем Pull Request

## Тестирование

> bundle exec guard

## Полезняшки

Скрипт для быстрого доступа к сервисам моего склада

> MS_LOGON=логин MS_PASSWORD=пароль ./script/rest.sh Country list > ./spec/fixtures/Country_list.raw

Если получаете 429 ошибку (too many requests) - лимит обращений по API от одного
аккаунта - 5 или 10 запросов в секунду (в секунду, Карл). Если не превышать его,
все будет хорошо - минутных или часовых лимитов нет.

## HTTP Таймаут

По-умолчанию таймаут равен 120 секунд, но его можно менять через переменную
окружения `MOYSKLAD_HTTP_TIMEOUT`

## Ссылочки

* Картапамяти по API http://www.mindmeister.com/246618635/online-moysklad-ru
* Документация для разработчииков https://support.moysklad.ru/hc/ru/sections/200561443-Разработчикам
* Неплохая схема API в json https://gist.github.com/dapi/22a0790db19a4ff51a37

## Другие биллиотеки

* PHP https://github.com/Tooyz/moysklad
* JavaScript/nodejs https://github.com/wmakeev/moysklad-client

## Присылайте пул-реквесты )

## Авторство

* Данил Письменный (brandymint.ru)