flowable 1.0.0
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 +7 -0
- data/CHANGELOG.md +83 -0
- data/LICENSE +21 -0
- data/README.md +872 -0
- data/bin/flowable +510 -0
- data/lib/flowable/flowable.rb +273 -0
- data/lib/flowable/resources/base.rb +44 -0
- data/lib/flowable/resources/bpmn_deployments.rb +90 -0
- data/lib/flowable/resources/bpmn_history.rb +228 -0
- data/lib/flowable/resources/case_definitions.rb +115 -0
- data/lib/flowable/resources/case_instances.rb +188 -0
- data/lib/flowable/resources/deployments.rb +87 -0
- data/lib/flowable/resources/executions.rb +134 -0
- data/lib/flowable/resources/history.rb +264 -0
- data/lib/flowable/resources/plan_item_instances.rb +131 -0
- data/lib/flowable/resources/process_definitions.rb +142 -0
- data/lib/flowable/resources/process_instances.rb +200 -0
- data/lib/flowable/resources/tasks.rb +281 -0
- data/lib/flowable/version.rb +37 -0
- data/lib/flowable/workflow.rb +444 -0
- data/lib/flowable.rb +9 -0
- data/lib/flowable_client/resources/bpmn_history.rb +228 -0
- data/lib/flowable_client/resources/process_definitions.rb +142 -0
- data/lib/flowable_client/resources/process_instances.rb +200 -0
- metadata +104 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../flowable'
|
|
4
|
+
|
|
5
|
+
module Flowable
|
|
6
|
+
# High-level DSL for workflow management
|
|
7
|
+
# Provides a more intuitive API for common workflow operations
|
|
8
|
+
module Workflow
|
|
9
|
+
class Case
|
|
10
|
+
attr_reader :client
|
|
11
|
+
attr_reader :case_key
|
|
12
|
+
attr_reader :instance
|
|
13
|
+
|
|
14
|
+
def initialize(client, case_key)
|
|
15
|
+
@client = client
|
|
16
|
+
@case_key = case_key
|
|
17
|
+
@instance = nil
|
|
18
|
+
@task_handlers = {}
|
|
19
|
+
@milestone_callbacks = {}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Start a new case instance
|
|
23
|
+
# @param variables [Hash] Initial variables
|
|
24
|
+
# @param business_key [String] Business key
|
|
25
|
+
# @return [self]
|
|
26
|
+
def start(variables: {}, business_key: nil)
|
|
27
|
+
@instance = client.case_instances.start_by_key(
|
|
28
|
+
case_key,
|
|
29
|
+
variables: variables,
|
|
30
|
+
business_key: business_key,
|
|
31
|
+
return_variables: true
|
|
32
|
+
)
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Load an existing case instance
|
|
37
|
+
# @param case_instance_id [String] Case instance ID
|
|
38
|
+
# @return [self]
|
|
39
|
+
def load(case_instance_id)
|
|
40
|
+
@instance = client.case_instances.get(case_instance_id)
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Find case by business key
|
|
45
|
+
# @param business_key [String] Business key
|
|
46
|
+
# @return [self, nil]
|
|
47
|
+
def find_by_business_key(business_key)
|
|
48
|
+
result = client.case_instances.list(
|
|
49
|
+
caseDefinitionKey: case_key,
|
|
50
|
+
businessKey: business_key,
|
|
51
|
+
size: 1
|
|
52
|
+
)
|
|
53
|
+
return nil if result['data'].empty?
|
|
54
|
+
|
|
55
|
+
@instance = result['data'].first
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Get case instance ID
|
|
60
|
+
def id
|
|
61
|
+
instance&.dig('id')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Get case state
|
|
65
|
+
def state
|
|
66
|
+
refresh! if instance
|
|
67
|
+
instance&.dig('state')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Check if case is active
|
|
71
|
+
def active?
|
|
72
|
+
state == 'active'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Check if case is completed
|
|
76
|
+
def completed?
|
|
77
|
+
instance&.dig('ended') == true || instance&.dig('completed') == true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Refresh case instance data from server
|
|
81
|
+
def refresh!
|
|
82
|
+
@instance = client.case_instances.get(id) if id
|
|
83
|
+
self
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Get all variables
|
|
87
|
+
def variables
|
|
88
|
+
return {} unless id
|
|
89
|
+
|
|
90
|
+
client.case_instances.variables(id).each_with_object({}) do |var, hash|
|
|
91
|
+
hash[var['name'].to_sym] = var['value']
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Get a single variable
|
|
96
|
+
def [](name)
|
|
97
|
+
variables[name.to_sym]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Set variables
|
|
101
|
+
def []=(name, value)
|
|
102
|
+
set(name => value)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Set multiple variables
|
|
106
|
+
def set(vars)
|
|
107
|
+
client.case_instances.set_variables(id, vars)
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Get stage overview
|
|
112
|
+
def stages
|
|
113
|
+
return [] unless id
|
|
114
|
+
|
|
115
|
+
client.case_instances.stage_overview(id).map do |stage|
|
|
116
|
+
Stage.new(stage)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Get current stage
|
|
121
|
+
def current_stage
|
|
122
|
+
stages.find(&:current?)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Get all tasks for this case
|
|
126
|
+
def tasks
|
|
127
|
+
return [] unless id
|
|
128
|
+
|
|
129
|
+
result = client.tasks.list(caseInstanceId: id)
|
|
130
|
+
result['data'].map { |t| Task.new(client, t) }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Get pending tasks (unassigned or assigned to current user)
|
|
134
|
+
def pending_tasks
|
|
135
|
+
tasks.reject(&:completed?)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Find task by name
|
|
139
|
+
def task(name)
|
|
140
|
+
tasks.find { |t| t.name == name }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Wait for a task to appear (polling)
|
|
144
|
+
# @param name [String] Task name
|
|
145
|
+
# @param timeout [Integer] Timeout in seconds
|
|
146
|
+
# @param interval [Integer] Poll interval in seconds
|
|
147
|
+
# @yield [Task] Block to execute when task is found
|
|
148
|
+
def wait_for_task(name, timeout: 30, interval: 1)
|
|
149
|
+
start_time = Time.now
|
|
150
|
+
loop do
|
|
151
|
+
task = self.task(name)
|
|
152
|
+
if task
|
|
153
|
+
yield task if block_given?
|
|
154
|
+
return task
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if Time.now - start_time > timeout
|
|
158
|
+
raise Error, "Timeout waiting for task '#{name}'"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
sleep interval
|
|
162
|
+
refresh!
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Register a task handler
|
|
167
|
+
# @param task_name [String] Task name to handle
|
|
168
|
+
# @yield [Task] Block to execute when task is available
|
|
169
|
+
def on_task(task_name, &block)
|
|
170
|
+
@task_handlers[task_name] = block
|
|
171
|
+
self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Process all pending tasks with registered handlers
|
|
175
|
+
def process_tasks!
|
|
176
|
+
pending_tasks.each do |task|
|
|
177
|
+
handler = @task_handlers[task.name]
|
|
178
|
+
handler&.call(task)
|
|
179
|
+
end
|
|
180
|
+
self
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Delete the case instance
|
|
184
|
+
def delete!
|
|
185
|
+
client.case_instances.delete(id) if id
|
|
186
|
+
@instance = nil
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Get identity links
|
|
190
|
+
def involved_users
|
|
191
|
+
return [] unless id
|
|
192
|
+
|
|
193
|
+
client.case_instances.identity_links(id)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Add involved user
|
|
197
|
+
def involve(user_id, type: 'participant')
|
|
198
|
+
client.case_instances.add_involved_user(id, user_id, type: type)
|
|
199
|
+
self
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class Process
|
|
204
|
+
attr_reader :client
|
|
205
|
+
attr_reader :process_key
|
|
206
|
+
attr_reader :instance
|
|
207
|
+
|
|
208
|
+
def initialize(client, process_key)
|
|
209
|
+
@client = client
|
|
210
|
+
@process_key = process_key
|
|
211
|
+
@instance = nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Start a new process instance
|
|
215
|
+
def start(variables: {}, business_key: nil)
|
|
216
|
+
@instance = client.process_instances.start_by_key(
|
|
217
|
+
process_key,
|
|
218
|
+
variables: variables,
|
|
219
|
+
business_key: business_key,
|
|
220
|
+
return_variables: true
|
|
221
|
+
)
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Load an existing process instance
|
|
226
|
+
def load(process_instance_id)
|
|
227
|
+
@instance = client.process_instances.get(process_instance_id)
|
|
228
|
+
self
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def id
|
|
232
|
+
instance&.dig('id')
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def ended?
|
|
236
|
+
instance&.dig('ended') == true
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def suspended?
|
|
240
|
+
instance&.dig('suspended') == true
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def refresh!
|
|
244
|
+
@instance = client.process_instances.get(id) if id
|
|
245
|
+
self
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def variables
|
|
249
|
+
return {} unless id
|
|
250
|
+
|
|
251
|
+
client.process_instances.variables(id).each_with_object({}) do |var, hash|
|
|
252
|
+
hash[var['name'].to_sym] = var['value']
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def set(vars)
|
|
257
|
+
client.process_instances.set_variables(id, vars)
|
|
258
|
+
self
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def suspend!
|
|
262
|
+
client.process_instances.suspend(id)
|
|
263
|
+
refresh!
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def activate!
|
|
267
|
+
client.process_instances.activate(id)
|
|
268
|
+
refresh!
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def delete!(reason: nil)
|
|
272
|
+
client.process_instances.delete(id, delete_reason: reason)
|
|
273
|
+
@instance = nil
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
class Task
|
|
278
|
+
attr_reader :client
|
|
279
|
+
attr_reader :data
|
|
280
|
+
|
|
281
|
+
def initialize(client, data)
|
|
282
|
+
@client = client
|
|
283
|
+
@data = data
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def id
|
|
287
|
+
data['id']
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def name
|
|
291
|
+
data['name']
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def description
|
|
295
|
+
data['description']
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def assignee
|
|
299
|
+
data['assignee']
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def owner
|
|
303
|
+
data['owner']
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def priority
|
|
307
|
+
data['priority']
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def due_date
|
|
311
|
+
data['dueDate']
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def created_at
|
|
315
|
+
data['createTime']
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def case_instance_id
|
|
319
|
+
data['caseInstanceId']
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def process_instance_id
|
|
323
|
+
data['processInstanceId']
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def completed?
|
|
327
|
+
!data['endTime'].nil? && !data['endTime'].to_s.empty?
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def assigned?
|
|
331
|
+
!assignee.nil?
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Claim the task
|
|
335
|
+
def claim(user)
|
|
336
|
+
client.tasks.claim(id, user)
|
|
337
|
+
@data['assignee'] = user
|
|
338
|
+
self
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Unclaim the task
|
|
342
|
+
def unclaim
|
|
343
|
+
client.tasks.unclaim(id)
|
|
344
|
+
@data['assignee'] = nil
|
|
345
|
+
self
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# Complete the task
|
|
349
|
+
def complete(variables: {}, outcome: nil)
|
|
350
|
+
client.tasks.complete(id, variables: variables, outcome: outcome)
|
|
351
|
+
self
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Delegate to another user
|
|
355
|
+
def delegate_to(user)
|
|
356
|
+
client.tasks.delegate(id, user)
|
|
357
|
+
self
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Resolve delegated task
|
|
361
|
+
def resolve
|
|
362
|
+
client.tasks.resolve(id)
|
|
363
|
+
self
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Get task variables
|
|
367
|
+
def variables(scope: nil)
|
|
368
|
+
client.tasks.variables(id, scope: scope).each_with_object({}) do |var, hash|
|
|
369
|
+
hash[var['name'].to_sym] = var['value']
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Set task variables
|
|
374
|
+
def set(vars, scope: 'local')
|
|
375
|
+
vars.each do |name, value|
|
|
376
|
+
client.tasks.update_variable(id, name.to_s, value, scope: scope)
|
|
377
|
+
end
|
|
378
|
+
self
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Update task properties
|
|
382
|
+
def update(attrs)
|
|
383
|
+
client.tasks.update(id, **attrs)
|
|
384
|
+
attrs.each { |k, v| @data[k.to_s] = v }
|
|
385
|
+
self
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Add candidate user
|
|
389
|
+
def add_candidate(user_id)
|
|
390
|
+
client.tasks.add_user_identity_link(id, user_id, type: 'candidate')
|
|
391
|
+
self
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Add candidate group
|
|
395
|
+
def add_candidate_group(group_id)
|
|
396
|
+
client.tasks.add_group_identity_link(id, group_id, type: 'candidate')
|
|
397
|
+
self
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
class Stage
|
|
402
|
+
attr_reader :data
|
|
403
|
+
|
|
404
|
+
def initialize(data)
|
|
405
|
+
@data = data
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def id
|
|
409
|
+
data['id']
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def name
|
|
413
|
+
data['name']
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def current?
|
|
417
|
+
data['current'] == true
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def ended?
|
|
421
|
+
data['ended'] == true
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def end_time
|
|
425
|
+
data['endTime']
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Factory methods for workflow DSL
|
|
430
|
+
module ClassMethods
|
|
431
|
+
def case_workflow(case_key)
|
|
432
|
+
Case.new(self, case_key)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def process_workflow(process_key)
|
|
436
|
+
Process.new(self, process_key)
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
class Client
|
|
442
|
+
include Workflow::ClassMethods
|
|
443
|
+
end
|
|
444
|
+
end
|
data/lib/flowable.rb
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FlowableClient
|
|
4
|
+
module Resources
|
|
5
|
+
class BpmnHistory < Base
|
|
6
|
+
# --- Historic Process Instances ---
|
|
7
|
+
|
|
8
|
+
# List historic process instances
|
|
9
|
+
# @param options [Hash] Query parameters
|
|
10
|
+
# @option options [String] :processInstanceId Filter by process instance ID
|
|
11
|
+
# @option options [String] :processDefinitionKey Filter by definition key
|
|
12
|
+
# @option options [String] :processDefinitionId Filter by definition ID
|
|
13
|
+
# @option options [String] :businessKey Filter by business key
|
|
14
|
+
# @option options [String] :involvedUser Filter by involved user
|
|
15
|
+
# @option options [Boolean] :finished Only finished instances
|
|
16
|
+
# @option options [Boolean] :includeProcessVariables Include variables
|
|
17
|
+
# @option options [String] :tenantId Filter by tenant
|
|
18
|
+
# @return [Hash] Paginated list of historic process instances
|
|
19
|
+
def process_instances(**options)
|
|
20
|
+
params = paginate_params(options)
|
|
21
|
+
%i[processInstanceId processDefinitionKey processDefinitionId businessKey
|
|
22
|
+
involvedUser superProcessInstanceId startedBy tenantId tenantIdLike].each do |key|
|
|
23
|
+
params[key] = options[key] if options[key]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
%i[finished includeProcessVariables withoutTenantId].each do |key|
|
|
27
|
+
params[key] = options[key] if options.key?(key)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
%i[finishedAfter finishedBefore startedAfter startedBefore].each do |key|
|
|
31
|
+
params[key] = format_date(options[key]) if options[key]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
client.get('service/history/historic-process-instances', params)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get a specific historic process instance
|
|
38
|
+
# @param process_instance_id [String] The process instance ID
|
|
39
|
+
# @return [Hash] Historic process instance details
|
|
40
|
+
def process_instance(process_instance_id)
|
|
41
|
+
client.get("service/history/historic-process-instances/#{process_instance_id}")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Delete a historic process instance
|
|
45
|
+
# @param process_instance_id [String] The process instance ID
|
|
46
|
+
# @return [Boolean] true if successful
|
|
47
|
+
def delete_process_instance(process_instance_id)
|
|
48
|
+
client.delete("service/history/historic-process-instances/#{process_instance_id}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Query historic process instances with complex filters
|
|
52
|
+
# @param query [Hash] Query body
|
|
53
|
+
# @return [Hash] Paginated list of historic process instances
|
|
54
|
+
def query_process_instances(query)
|
|
55
|
+
client.post('service/query/historic-process-instances', query)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Get identity links for a historic process instance
|
|
59
|
+
# @param process_instance_id [String] The process instance ID
|
|
60
|
+
# @return [Array<Hash>] List of identity links
|
|
61
|
+
def process_instance_identity_links(process_instance_id)
|
|
62
|
+
client.get("service/history/historic-process-instances/#{process_instance_id}/identitylinks")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# --- Historic Activity Instances ---
|
|
66
|
+
|
|
67
|
+
# List historic activity instances
|
|
68
|
+
# @param options [Hash] Query parameters
|
|
69
|
+
# @option options [String] :activityId Filter by activity ID
|
|
70
|
+
# @option options [String] :activityName Filter by activity name
|
|
71
|
+
# @option options [String] :activityType Filter by type (userTask, serviceTask, etc.)
|
|
72
|
+
# @option options [String] :processInstanceId Filter by process instance
|
|
73
|
+
# @option options [String] :processDefinitionId Filter by process definition
|
|
74
|
+
# @option options [Boolean] :finished Only finished activities
|
|
75
|
+
# @return [Hash] Paginated list of historic activities
|
|
76
|
+
def activity_instances(**options)
|
|
77
|
+
params = paginate_params(options)
|
|
78
|
+
%i[activityId activityName activityType processInstanceId processDefinitionId
|
|
79
|
+
executionId taskAssignee tenantId tenantIdLike].each do |key|
|
|
80
|
+
params[key] = options[key] if options[key]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
params[:finished] = options[:finished] if options.key?(:finished)
|
|
84
|
+
params[:withoutTenantId] = options[:withoutTenantId] if options.key?(:withoutTenantId)
|
|
85
|
+
|
|
86
|
+
client.get('service/history/historic-activity-instances', params)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Query historic activities with complex filters
|
|
90
|
+
# @param query [Hash] Query body
|
|
91
|
+
# @return [Hash] Paginated list of historic activities
|
|
92
|
+
def query_activity_instances(query)
|
|
93
|
+
client.post('service/query/historic-activity-instances', query)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# --- Historic Task Instances ---
|
|
97
|
+
|
|
98
|
+
# List historic task instances
|
|
99
|
+
# @param options [Hash] Query parameters
|
|
100
|
+
# @option options [String] :taskId Filter by task ID
|
|
101
|
+
# @option options [String] :processInstanceId Filter by process instance
|
|
102
|
+
# @option options [String] :processDefinitionId Filter by process definition
|
|
103
|
+
# @option options [String] :taskName Filter by name
|
|
104
|
+
# @option options [String] :taskAssignee Filter by assignee
|
|
105
|
+
# @option options [Boolean] :finished Only finished tasks
|
|
106
|
+
# @return [Hash] Paginated list of historic tasks
|
|
107
|
+
def task_instances(**options)
|
|
108
|
+
params = paginate_params(options)
|
|
109
|
+
%i[taskId processInstanceId processDefinitionId processDefinitionKey
|
|
110
|
+
taskName taskNameLike taskDescription taskDescriptionLike
|
|
111
|
+
taskDefinitionKey taskDeleteReason taskDeleteReasonLike
|
|
112
|
+
taskAssignee taskAssigneeLike taskOwner taskOwnerLike
|
|
113
|
+
taskInvolvedUser taskPriority parentTaskId tenantId tenantIdLike].each do |key|
|
|
114
|
+
params[key] = options[key] if options[key]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
%i[finished processFinished withoutDueDate includeTaskLocalVariables withoutTenantId].each do |key|
|
|
118
|
+
params[key] = options[key] if options.key?(key)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
%i[dueDate dueDateAfter dueDateBefore taskCompletedOn taskCompletedAfter
|
|
122
|
+
taskCompletedBefore taskCreatedOn taskCreatedBefore taskCreatedAfter].each do |key|
|
|
123
|
+
params[key] = format_date(options[key]) if options[key]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
client.get('service/history/historic-task-instances', params)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Get a specific historic task
|
|
130
|
+
# @param task_id [String] The task ID
|
|
131
|
+
# @return [Hash] Historic task details
|
|
132
|
+
def task_instance(task_id)
|
|
133
|
+
client.get("service/history/historic-task-instances/#{task_id}")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Delete a historic task
|
|
137
|
+
# @param task_id [String] The task ID
|
|
138
|
+
# @return [Boolean] true if successful
|
|
139
|
+
def delete_task_instance(task_id)
|
|
140
|
+
client.delete("service/history/historic-task-instances/#{task_id}")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Query historic tasks with complex filters
|
|
144
|
+
# @param query [Hash] Query body
|
|
145
|
+
# @return [Hash] Paginated list of historic tasks
|
|
146
|
+
def query_task_instances(query)
|
|
147
|
+
client.post('service/query/historic-task-instances', query)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# --- Historic Variable Instances ---
|
|
151
|
+
|
|
152
|
+
# List historic variable instances
|
|
153
|
+
# @param options [Hash] Query parameters
|
|
154
|
+
# @option options [String] :processInstanceId Filter by process instance
|
|
155
|
+
# @option options [String] :taskId Filter by task
|
|
156
|
+
# @option options [Boolean] :excludeTaskVariables Exclude task variables
|
|
157
|
+
# @option options [String] :variableName Filter by variable name
|
|
158
|
+
# @return [Hash] Paginated list of historic variables
|
|
159
|
+
def variable_instances(**options)
|
|
160
|
+
params = paginate_params(options)
|
|
161
|
+
%i[processInstanceId taskId variableName variableNameLike].each do |key|
|
|
162
|
+
params[key] = options[key] if options[key]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
params[:excludeTaskVariables] = options[:excludeTaskVariables] if options.key?(:excludeTaskVariables)
|
|
166
|
+
|
|
167
|
+
client.get('service/history/historic-variable-instances', params)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Query historic variables with complex filters
|
|
171
|
+
# @param query [Hash] Query body
|
|
172
|
+
# @return [Hash] Paginated list of historic variables
|
|
173
|
+
def query_variable_instances(query)
|
|
174
|
+
client.post('service/query/historic-variable-instances', query)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# --- Historic Detail ---
|
|
178
|
+
|
|
179
|
+
# List historic details (variable updates, form properties)
|
|
180
|
+
# @param options [Hash] Query parameters
|
|
181
|
+
# @option options [String] :processInstanceId Filter by process instance
|
|
182
|
+
# @option options [String] :executionId Filter by execution
|
|
183
|
+
# @option options [String] :activityInstanceId Filter by activity instance
|
|
184
|
+
# @option options [String] :taskId Filter by task
|
|
185
|
+
# @option options [Boolean] :selectOnlyFormProperties Only form properties
|
|
186
|
+
# @option options [Boolean] :selectOnlyVariableUpdates Only variable updates
|
|
187
|
+
# @return [Hash] Paginated list of historic details
|
|
188
|
+
def details(**options)
|
|
189
|
+
params = paginate_params(options)
|
|
190
|
+
%i[processInstanceId executionId activityInstanceId taskId].each do |key|
|
|
191
|
+
params[key] = options[key] if options[key]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if options.key?(:selectOnlyFormProperties)
|
|
195
|
+
params[:selectOnlyFormProperties] =
|
|
196
|
+
options[:selectOnlyFormProperties]
|
|
197
|
+
end
|
|
198
|
+
if options.key?(:selectOnlyVariableUpdates)
|
|
199
|
+
params[:selectOnlyVariableUpdates] =
|
|
200
|
+
options[:selectOnlyVariableUpdates]
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
client.get('service/history/historic-detail', params)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Query historic details with complex filters
|
|
207
|
+
# @param query [Hash] Query body
|
|
208
|
+
# @return [Hash] Paginated list of historic details
|
|
209
|
+
def query_details(query)
|
|
210
|
+
client.post('service/query/historic-detail', query)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Aliases for backward compatibility
|
|
214
|
+
alias tasks task_instances
|
|
215
|
+
alias activities activity_instances
|
|
216
|
+
alias variables variable_instances
|
|
217
|
+
|
|
218
|
+
private
|
|
219
|
+
|
|
220
|
+
def format_date(date)
|
|
221
|
+
return date if date.is_a?(String)
|
|
222
|
+
return date.iso8601 if date.respond_to?(:iso8601)
|
|
223
|
+
|
|
224
|
+
date.to_s
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|