tehportal 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c5a8fa924393d1efda5585ea6666232b67310de
4
- data.tar.gz: 5f6601b8bd473d1b691c56258bbe1a8814140a86
3
+ metadata.gz: 89c7023c36b3c4aaf5d169c02278e63f57ebbe08
4
+ data.tar.gz: b671e3f9bd9a34c230f865e78560bb2598179d15
5
5
  SHA512:
6
- metadata.gz: 1392c6f43ed7369ccbc8b5ce71d26e34a0ade9363d5dd718df3a3d45e511bc19e0334aecc4bad58d81bcc8c907b1a2cda3d4828358b76150022cc6a11197849b
7
- data.tar.gz: 2b70144a02c70d0a8fc3229a496751c94426fbcfc47f8115ace6182e7eab7c9e7184ce8fb4546311cff2e0da71680230e1ca85d7ef74febc18193f9c803ee2cf
6
+ metadata.gz: ce27c58dc530915a96c0c2a99bf57d52cf4c22c562e658b62eb5e8ef1fb826f60d625e1b5de22bf333e28d4082c3fc42f2683b32a556ad8f4a5ae3bda9ded389
7
+ data.tar.gz: f698526fb5feefedd5d9c1925b5a768f9eecb841ffa9c7aabb14e0f351933939b6e1f44e2d3c5e46fcddbea23ecbaff8ea3777c0d828a75ef5644308b79571f3
data/README.md CHANGED
@@ -3,30 +3,6 @@
3
3
  ## Описание
4
4
  Данный gem это ядро для работы с remedy и возможно с другими системами.
5
5
 
6
- ## Модели
7
- Все сервиси группируем - инциденты, изменения, проблемы, задачи и тд. Для каждой группы делаем модель с базовым классом - **Tehportal::Model**.
8
- В модели делаем описание всех сервисов в виде хэша:
9
-
10
- @@services = {
11
- show: 'ATC:HPD:AKEOS-Portal-Get-Incident-WorkInfo',
12
- list: 'ATC:INC:AKEOS-List',
13
- create: 'ATC:INC:AKEOS-Create',
14
- update: 'ATC:INC:AKEOS-Modify'
15
- }
16
-
17
- Где ключ данного хэша будет соответствовать action-методу в соответствующем контроллере.
18
- Также в базовом классе моделе реализован запрос к серверу(сейчас через method_missing, после рефакторинга с помощью class_eval).
19
- Модели называем во множественном числе(например: Tehportal::Incidents), чтобы соответствовало названию контроллера.
20
-
21
- **ВАЖНО:** Т.к. в remedy важен порядок передаваемых ему полей в моделе реализован механизм, который расставляем параметры в нжном порядке. Нужно просто передать параметры.
22
-
23
- ### 1.Инциденты
24
- Модель: **Tehportal::Incidents**
25
- ### 2.Изменения
26
- ### 3.Проблемы
27
- Модель: **Tehportal::Problems**
28
- ### 4.Релизы
29
-
30
6
  ## Контроллеры/API
31
7
  Все контроллеры для работы с remedy наследуются от **RemedyBaseController**. Перед запуском любого action-метода срабатывает хук который отпределяет
32
8
  с какой моделью работать данному контроллеру.
@@ -36,69 +12,6 @@
36
12
  Базовый url: _/tp/remedy_
37
13
 
38
14
  Параметры который пойдут на вход Remedy передаются в массиве data (пример: data[ID]=23&data[Description]=New_Message)
39
- Для action может быть несколько операций, они передаются параметром operation(пример: operation=INCGetList-InWork)
40
-
41
- ### 1.Инциденты
42
- #### Список инцидентов
43
-
44
- *URL:* GET /incidents/
45
-
46
- |Операция|Описание|Параметры|
47
- |--------|--------|---------|
48
- | _INCGetList-InWork_ | Назначенные на меня со статусом "открытые" |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
49
- | _INCGetList-SLABreached-My_ | Назначенные на меня со статусом "нарушенные" |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
50
- | _INCGetList-Pending-My_ | Назначенные на меня со статусом "в ожидании" |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
51
- | _INC_Created_By_Me_InWork_ | Созданные мной |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
52
- | _INCGetList-SLABreached-OnMyGroup_ | Назначенные на группу со статусом "просроченные"|startRecord - offset для списка<br /> maxLimit - limit для списка<br />Group - Название группы|
53
- | _INCGetList-InWork-OnMyGroup_ | Назначенные на группу со статусом "открытые"|startRecord - offset для списка<br /> maxLimit - limit для списка<br />Group - Название группы|
54
- | _NCGetList-Pending-OnMyGroup_ | Назначенные на группу со статусом "в ожидании" |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Group - Название группы|
55
-
56
- ##### *URL:* GET /incidents/:id - Просмотр инцидента
57
- ##### *URL:* GET /incidents/:id/associations - Просмотр инцидента: свзяи
58
- ##### *URL:* GET /incidents/:id/tasks - Просмотр инцидента: задачи
59
- ##### *URL:* GET /incidents/:id/times - Просмотр инцидента: затраченное время
60
-
61
- ### 2.Задачи
62
- #### Список задач
63
-
64
- *URL:* GET /tasks/
65
-
66
- |Операция|Описание|Параметры|
67
- |--------|--------|---------|
68
- | _TSK_My_InWork_ | Назначенные на меня со статусом "открытые" |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
69
- | _TSK_Created_By_Me_InWork_ | Созданные мной |startRecord - offset для списка<br /> maxLimit - limit для списка<br />Login - логин пользователя|
70
- | _TSK_OnMyGroup_InWork_ | Назначенные на группу со статусом "открытые"|startRecord - offset для списка<br /> maxLimit - limit для списка<br />Group - Название группы|
71
-
72
- ##### *URL:* GET /incidents/:id - Просмотр задачи
73
- ##### *URL:* GET /tasks/:id/comments - Просмотр задачи: комментарии
74
- ##### *URL:* GET /tasks/:id/times - Просмотр задачи: затраченное время
75
-
76
-
77
- ### 3.Изменения
78
- ### 4.Проблемы
79
- Контроллер: **ProblemsController**
80
- Методы:
81
-
82
- * list
83
-
84
- команда:
85
- `GET /tp/remedy/problems?operation=[операция]`
86
-
87
- операции:
88
-
89
- - InWorkMy
90
- - InWorkGroup
91
- - InWorkAllGroups
92
-
93
- * show
94
- команда:
95
- `GET /tp/remedy/problems/[id]`
96
-
97
- * create
98
- команда:
99
- `POST /tp/remedy/problems`
100
-
101
- ### 5.Релизы
102
15
 
103
16
  # Установка
104
17
 
@@ -109,9 +22,13 @@
109
22
  1. В приложении необходимо создать инициализатор gem'а:
110
23
 
111
24
  `Tehportal.configure do |config|
25
+
112
26
  config.url = 'http://example.com'
27
+
113
28
  config.server = 'example-server'
29
+
114
30
  config.endpoint = 'http://example.com/services/ARService'
31
+
115
32
  end`
116
33
 
117
34
  1. Роутинг:
@@ -50,8 +50,12 @@ class RemedyController < Tehportal.config.parent_controller.constantize
50
50
  private
51
51
 
52
52
  def render_remedy_json(data)
53
- prepared = data.except('@xmlns:ns0', '@xmlns:xsd', '@xmlns:xsi')
54
- render json: (prepared.blank? && data.length != 3) ? nil : prepared
53
+ if data.is_a? Array
54
+ render json: data
55
+ else
56
+ prepared = data.except!('@xmlns:ns0', '@xmlns:xsd', '@xmlns:xsi')
57
+ render json: (prepared.blank? && data.length != 3) ? {} : prepared
58
+ end
55
59
  end
56
60
 
57
61
  end
@@ -20,10 +20,27 @@ module Operation
20
20
 
21
21
  # Добавляем синглтон метод к классу модели
22
22
  define_singleton_method(name) do |*args|
23
+ args[0] ||= {}
23
24
  client = args[0].delete(:client) || Tehportal.client
24
25
  message = options[:defaults].merge(args[0])
25
-
26
- client.request(service, operation, message)
26
+
27
+ unless options[:cache] and result = Rails.cache.fetch([:tehportal, service, operation, message])
28
+ result = client.request(service, operation, message)
29
+ if options[:cache] and !result.include?(:errorMessage)
30
+ Rails.cache.write([:tehportal, service, operation, message], result, expires_in: options[:cache])
31
+ end
32
+ end
33
+
34
+ if options[:as] == :list
35
+ if result.include?(:errorMessage)
36
+ if result[:errorMessage] =~ /^ERROR \(302\)/
37
+ result = []
38
+ end
39
+ else
40
+ result = Array.wrap(result['getListValues'] || [result])
41
+ end
42
+ end
43
+ result
27
44
  end
28
45
  end
29
46
  end
@@ -1,10 +1,12 @@
1
1
  module Tehportal
2
2
  class RemedyClient
3
- delegate :config, to: :Tehportal
3
+ attr_reader :config
4
4
 
5
- def initialize(login = nil, password = nil)
5
+ def initialize(login = nil, password = nil, **config_override)
6
6
  @login, @password = login, password
7
7
  @definitions = Rails.cache.read('tp.remedy.definitions') || {}
8
+ @config = Tehportal.config
9
+ config_override.each {|k, v| @config.send "#{k}=", v}
8
10
  end
9
11
 
10
12
  # Выполнение запроса к сервису
@@ -15,6 +17,7 @@ module Tehportal
15
17
  # e.g.: {"Status" => "Pending"}
16
18
  def request(service, method, body = {})
17
19
  message = {}
20
+ body = body.with_indifferent_access
18
21
  operation_map = operation_map(service, method)
19
22
 
20
23
  operation_map[:input].each do |key|
@@ -32,7 +35,7 @@ module Tehportal
32
35
  log: true,
33
36
  logger: Rails.logger,
34
37
  log_level: :debug,
35
- filters: [:password])
38
+ filters: [:password, *[1,2,3].map {|i| :"z2AF_Work_Log0#{i}_attachmentData"}, *[1,2,3].map {|i| :"WLG_Attach#{i}_File"}])
36
39
 
37
40
  response = client.call(method, message: message, soap_action: "urn:#{service}/#{method}", advanced_typecasting: false)
38
41
 
@@ -67,6 +70,41 @@ module Tehportal
67
70
 
68
71
  @definitions[service]
69
72
  end
73
+
74
+ # Хелперы для #operations_map и, в частности, для дебага не очень прямых сервисов
75
+ def operation_fields(op_name, elements: nil, types: nil)
76
+ unless elements and types
77
+ unless op_name['/']
78
+ raise ArgumentError, 'Нужно передать либо полное имя сервиса, e.g. ATC:FoundationCatalogs/SupportGroups, либо :elements и :types'
79
+ end
80
+ service, op_name = op_name.split '/'
81
+ elements, types = elements_and_types(service)
82
+ end
83
+ type_name = elements.find {|e| e['@name'] == op_name}['@type'].sub(/^[^:]+:/, '')
84
+ type_input = types.find {|t| t['@name'] == type_name}['sequence'] || {}
85
+ Array.wrap(type_input['element'])
86
+ end
87
+
88
+ def definition_schema(defs)
89
+ schema = defs['types'].blank? ? {} : defs['types']['schema']
90
+ if schema.is_a? Array # для Ремеди Росреестра; у сибирского всегда только 1 schema
91
+ main_schema = schema[0]
92
+ schema.sum(&:keys).uniq.each {|k|
93
+ unless k['@']
94
+ main_schema[k] = schema.sum {|i| Array.wrap(i[k])}
95
+ end
96
+ }
97
+ main_schema
98
+ else
99
+ schema
100
+ end
101
+ end
102
+
103
+ def elements_and_types(service)
104
+ schema = definition_schema(definitions(service))
105
+ [Array.wrap(schema['element']),
106
+ Array.wrap(schema['complexType'])]
107
+ end
70
108
 
71
109
  # Определение доступных операций и их характеристик
72
110
  # в соответствии с wsdl:definition по указанному сервису
@@ -75,10 +113,8 @@ module Tehportal
75
113
  # e.g.: ATC:INC:AKEOS-List
76
114
  def operations_map(service)
77
115
  defs = definitions(service)
78
- schema = defs['types']['schema']
116
+ elements, types = elements_and_types(service)
79
117
  messages = Array.wrap(defs['message'])
80
- elements = Array.wrap(schema['element'])
81
- types = Array.wrap(schema['complexType'])
82
118
  operations = Array.wrap(defs['portType']['operation'])
83
119
 
84
120
  res = operations.map do |op|
@@ -90,14 +126,10 @@ module Tehportal
90
126
  # undasherize для удобства обхода (совместимо с текущим кодом)
91
127
  element_name.tr! '-', '_'
92
128
 
93
- type_name = elements.find {|e| e['@name'] == op_name}['@type'].sub(/^[^:]+:/, '')
94
- type_input = types.find {|t| t['@name'] == type_name}['sequence']
95
- if type_input
96
- fields = Array.wrap(type_input['element'])
97
- field_names = fields.map {|f| f['@name']}
98
- end
129
+ fields = operation_fields op_name, elements: elements, types: types
130
+ field_names = fields.map {|f| f['@name']}
99
131
 
100
- [op_name, {output: element_name, input: Array.wrap(field_names)}]
132
+ [op_name, {output: element_name, input: field_names}]
101
133
  end
102
134
 
103
135
  Hash[res]
@@ -1,3 +1,3 @@
1
1
  module Tehportal
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tehportal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - AT Consulting