petri_flow 0.1.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/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +34 -0
- data/app/assets/config/wf_manifest.js +2 -0
- data/app/assets/javascripts/wf/application.js +4 -0
- data/app/assets/stylesheets/wf/application.scss +2 -0
- data/app/assets/stylesheets/wf/arcs.css +4 -0
- data/app/assets/stylesheets/wf/cases.css +4 -0
- data/app/assets/stylesheets/wf/comments.css +4 -0
- data/app/assets/stylesheets/wf/fields.css +4 -0
- data/app/assets/stylesheets/wf/forms.css +4 -0
- data/app/assets/stylesheets/wf/guards.css +4 -0
- data/app/assets/stylesheets/wf/places.css +4 -0
- data/app/assets/stylesheets/wf/transitions.css +4 -0
- data/app/assets/stylesheets/wf/workflows.css +4 -0
- data/app/assets/stylesheets/wf/workitem_assignments.css +4 -0
- data/app/assets/stylesheets/wf/workitems.css +4 -0
- data/app/controllers/wf/application_controller.rb +14 -0
- data/app/controllers/wf/arcs_controller.rb +61 -0
- data/app/controllers/wf/cases_controller.rb +48 -0
- data/app/controllers/wf/comments_controller.rb +30 -0
- data/app/controllers/wf/fields_controller.rb +54 -0
- data/app/controllers/wf/forms_controller.rb +59 -0
- data/app/controllers/wf/guards_controller.rb +58 -0
- data/app/controllers/wf/places_controller.rb +53 -0
- data/app/controllers/wf/transitions_controller.rb +69 -0
- data/app/controllers/wf/workflows_controller.rb +59 -0
- data/app/controllers/wf/workitem_assignments_controller.rb +30 -0
- data/app/controllers/wf/workitems_controller.rb +79 -0
- data/app/helpers/wf/application_helper.rb +6 -0
- data/app/helpers/wf/arcs_helper.rb +6 -0
- data/app/helpers/wf/cases_helper.rb +6 -0
- data/app/helpers/wf/comments_helper.rb +6 -0
- data/app/helpers/wf/fields_helper.rb +6 -0
- data/app/helpers/wf/forms_helper.rb +6 -0
- data/app/helpers/wf/guards_helper.rb +6 -0
- data/app/helpers/wf/places_helper.rb +6 -0
- data/app/helpers/wf/transitions_helper.rb +6 -0
- data/app/helpers/wf/workflows_helper.rb +6 -0
- data/app/helpers/wf/workitem_assignments_helper.rb +6 -0
- data/app/helpers/wf/workitems_helper.rb +6 -0
- data/app/jobs/wf/application_job.rb +6 -0
- data/app/jobs/wf/fire_timed_workitem_job.rb +15 -0
- data/app/mailers/wf/application_mailer.rb +8 -0
- data/app/models/wf/application_record.rb +7 -0
- data/app/models/wf/arc.rb +42 -0
- data/app/models/wf/callbacks/assignment_default.rb +12 -0
- data/app/models/wf/callbacks/deadline_default.rb +11 -0
- data/app/models/wf/callbacks/enable_default.rb +11 -0
- data/app/models/wf/callbacks/fire_default.rb +11 -0
- data/app/models/wf/callbacks/hold_timeout_default.rb +11 -0
- data/app/models/wf/callbacks/notification_default.rb +11 -0
- data/app/models/wf/callbacks/time_default.rb +11 -0
- data/app/models/wf/callbacks/unassignment_default.rb +11 -0
- data/app/models/wf/case.rb +44 -0
- data/app/models/wf/case_assignment.rb +22 -0
- data/app/models/wf/case_command/add_comment.rb +17 -0
- data/app/models/wf/case_command/add_manual_assignment.rb +17 -0
- data/app/models/wf/case_command/add_token.rb +20 -0
- data/app/models/wf/case_command/add_workitem_assignment.rb +35 -0
- data/app/models/wf/case_command/begin_workitem_action.rb +33 -0
- data/app/models/wf/case_command/cancel.rb +17 -0
- data/app/models/wf/case_command/cancel_workitem.rb +20 -0
- data/app/models/wf/case_command/clear_manual_assignments.rb +16 -0
- data/app/models/wf/case_command/clear_workitem_assignments.rb +20 -0
- data/app/models/wf/case_command/consume_token.rb +23 -0
- data/app/models/wf/case_command/enable_transitions.rb +33 -0
- data/app/models/wf/case_command/end_workitem_action.rb +25 -0
- data/app/models/wf/case_command/finish_workitem.rb +18 -0
- data/app/models/wf/case_command/finished_p.rb +28 -0
- data/app/models/wf/case_command/fire_message_transition.rb +20 -0
- data/app/models/wf/case_command/fire_transition_internal.rb +41 -0
- data/app/models/wf/case_command/lock_token.rb +21 -0
- data/app/models/wf/case_command/new.rb +17 -0
- data/app/models/wf/case_command/release_token.rb +20 -0
- data/app/models/wf/case_command/remove_manual_assignment.rb +17 -0
- data/app/models/wf/case_command/remove_workitem_assignment.rb +24 -0
- data/app/models/wf/case_command/resume.rb +17 -0
- data/app/models/wf/case_command/set_workitem_assignments.rb +32 -0
- data/app/models/wf/case_command/start_case.rb +19 -0
- data/app/models/wf/case_command/start_workitem.rb +26 -0
- data/app/models/wf/case_command/suspend.rb +17 -0
- data/app/models/wf/case_command/sweep_automatic_transitions.rb +31 -0
- data/app/models/wf/case_command/sweep_timed_transitions.rb +16 -0
- data/app/models/wf/case_command/workitem_action.rb +20 -0
- data/app/models/wf/comment.rb +21 -0
- data/app/models/wf/demo_target.rb +18 -0
- data/app/models/wf/entry.rb +33 -0
- data/app/models/wf/field.rb +53 -0
- data/app/models/wf/field_value.rb +30 -0
- data/app/models/wf/form.rb +18 -0
- data/app/models/wf/group.rb +21 -0
- data/app/models/wf/guard.rb +73 -0
- data/app/models/wf/party.rb +22 -0
- data/app/models/wf/place.rb +28 -0
- data/app/models/wf/token.rb +37 -0
- data/app/models/wf/transition.rb +49 -0
- data/app/models/wf/transition_static_assignment.rb +21 -0
- data/app/models/wf/user.rb +26 -0
- data/app/models/wf/workflow.rb +182 -0
- data/app/models/wf/workitem.rb +78 -0
- data/app/models/wf/workitem_assignment.rb +19 -0
- data/app/views/layouts/wf/_alert.html.erb +4 -0
- data/app/views/layouts/wf/_footer.html.erb +13 -0
- data/app/views/layouts/wf/_nav.html.erb +13 -0
- data/app/views/layouts/wf/_notice.html.erb +4 -0
- data/app/views/layouts/wf/application.html.erb +34 -0
- data/app/views/wf/arcs/_form.html.erb +40 -0
- data/app/views/wf/arcs/edit.html.erb +1 -0
- data/app/views/wf/arcs/new.html.erb +1 -0
- data/app/views/wf/arcs/show.html.erb +67 -0
- data/app/views/wf/cases/_form.html.erb +27 -0
- data/app/views/wf/cases/index.html.erb +35 -0
- data/app/views/wf/cases/new.html.erb +1 -0
- data/app/views/wf/cases/show.html.erb +113 -0
- data/app/views/wf/comments/new.html.erb +27 -0
- data/app/views/wf/fields/_form.html.erb +42 -0
- data/app/views/wf/fields/edit.html.erb +1 -0
- data/app/views/wf/fields/new.html.erb +1 -0
- data/app/views/wf/forms/_form.html.erb +32 -0
- data/app/views/wf/forms/edit.html.erb +1 -0
- data/app/views/wf/forms/index.html.erb +32 -0
- data/app/views/wf/forms/new.html.erb +1 -0
- data/app/views/wf/forms/show.html.erb +53 -0
- data/app/views/wf/guards/_form.html.erb +43 -0
- data/app/views/wf/guards/edit.html.erb +1 -0
- data/app/views/wf/guards/new.html.erb +1 -0
- data/app/views/wf/places/_form.html.erb +43 -0
- data/app/views/wf/places/edit.html.erb +1 -0
- data/app/views/wf/places/new.html.erb +1 -0
- data/app/views/wf/transitions/_form.html.erb +92 -0
- data/app/views/wf/transitions/edit.html.erb +1 -0
- data/app/views/wf/transitions/new.html.erb +1 -0
- data/app/views/wf/workflows/_form.html.erb +32 -0
- data/app/views/wf/workflows/edit.html.erb +1 -0
- data/app/views/wf/workflows/index.html.erb +38 -0
- data/app/views/wf/workflows/new.html.erb +1 -0
- data/app/views/wf/workflows/show.html.erb +177 -0
- data/app/views/wf/workitem_assignments/new.html.erb +27 -0
- data/app/views/wf/workitems/index.html.erb +68 -0
- data/app/views/wf/workitems/pre_finish.html.erb +33 -0
- data/app/views/wf/workitems/show.html.erb +211 -0
- data/config/routes.rb +30 -0
- data/db/migrate/20200130201043_init.rb +226 -0
- data/db/migrate/20200130201641_init_some_data.rb +15 -0
- data/db/migrate/20200131200455_create_wf_entries.rb +19 -0
- data/db/migrate/20200201001543_add_target_field_name_for_guard.rb +7 -0
- data/lib/tasks/wf_tasks.rake +5 -0
- data/lib/wf/engine.rb +10 -0
- data/lib/wf/version.rb +5 -0
- data/lib/wf.rb +7 -0
- metadata +312 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class CancelWorkitem
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise("The workitem is not in state #{workitem.state}") unless workitem.started?
|
13
|
+
Wf::ApplicationRecord.transaction do
|
14
|
+
workitem.update!(state: :canceled, :canceled_at: Time.zone.now)
|
15
|
+
ReleaseToken.call(workitem)
|
16
|
+
SweepAutomaticTransitions.call(workitem.case)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class ClearManualAssignments
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case, :transition
|
7
|
+
def initialize(wf_case, transition)
|
8
|
+
@wf_case = wf_case
|
9
|
+
@transition = transition
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
wf_case.case_assignments.where(transition: transition).find_each(&:destroy)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class ClearWorkitemAssignments
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem, :permanent
|
7
|
+
def initialize(workitem, permanent = true)
|
8
|
+
@workitem = workitem
|
9
|
+
@permanent = permanent
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
Wf::ApplicationRecord.transaction do
|
14
|
+
ClearManualAssignments.call(workitem.case, workitem.transition) if permanent
|
15
|
+
workitem.workitem_assignments.delete_all
|
16
|
+
workitem.transition.unassignment_callback.constantize.new(workitem.id).perform
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class ConsumeToken
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case, :place, :locked_item
|
7
|
+
def initialize(wf_case, place, locked_item = nil)
|
8
|
+
@wf_case = wf_case
|
9
|
+
@place = place
|
10
|
+
@locked_item = locked_item
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
Wf::ApplicationRecord.transaction do
|
15
|
+
if locked_item
|
16
|
+
wf_case.tokens.where(place: place, state: :locked, locked_workitem_id: locked_item.id).update(consumed_at: Time.zone.now, state: :consumed)
|
17
|
+
else
|
18
|
+
wf_case.tokens.where(id: wf_case.tokens.where(place: place, state: :free).first&.id).update(consumed_at: Time.zone.now, state: :consumed)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class EnableTransitions
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
wf_case.workitems.enabled.each do |workitem|
|
14
|
+
workitem.update!(state: :overridden, overridden_at: Time.zone.now) unless wf_case.can_fire?(workitem.transition)
|
15
|
+
end
|
16
|
+
wf_case.workflow.transitions.each do |transition|
|
17
|
+
next unless wf_case.can_fire?(transition) && !transition.workitems.where(case: wf_case, state: %i[enabled started]).exists?
|
18
|
+
|
19
|
+
trigger_time = Time.zone.now + transition.trigger_limit.minutes if transition.trigger_limit && transition.time?
|
20
|
+
workitem = wf_case.workitems.create!(
|
21
|
+
workflow: wf_case.workflow,
|
22
|
+
transition: transition,
|
23
|
+
state: :enabled,
|
24
|
+
trigger_time: trigger_time
|
25
|
+
)
|
26
|
+
Wf::FireTimedWorkitemJob.set(wait: transition.trigger_limit.minutes).perform_later(workitem.id) if trigger_time
|
27
|
+
SetWorkitemAssignments.call(workitem)
|
28
|
+
workitem.transition.unassignment_callback.constantize.new(workitem.id).perform_now if workitem.workitem_assignments.count == 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class EndWorkitemAction
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem, :action, :user
|
7
|
+
def initialize(workitem, user, action = :start)
|
8
|
+
@workitem = workitem
|
9
|
+
@action = action
|
10
|
+
@user = user
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
if action == :start
|
15
|
+
StartWorkitem.call(workitem, user)
|
16
|
+
elsif action == :finish
|
17
|
+
FinishWorkitem.call(workitem, user)
|
18
|
+
elsif action == :cancel
|
19
|
+
CancelWorkitem.call(workitem, user)
|
20
|
+
elsif action == :comment
|
21
|
+
raise("Unknown action #{action}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class FinishWorkitem
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
FireTransitionInternal.call(workitem)
|
14
|
+
SweepAutomaticTransitions.call(workitem.case)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class FinishedP
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
return true if wf_case.finished?
|
13
|
+
|
14
|
+
end_place = wf_case.workflow.places.end.first
|
15
|
+
end_place_token_num = Wf::ApplicationRecord.uncached { wf_case.tokens.where(place: end_place).count }
|
16
|
+
if end_place_token_num == 0
|
17
|
+
false
|
18
|
+
else
|
19
|
+
free_and_locked_token_num = wf_case.tokens.where(place: end_place).where(state: %i[free locked]).count
|
20
|
+
raise("The workflow net is misconstructed: Some parallel executions have not finished.") if free_and_locked_token_num > 1
|
21
|
+
|
22
|
+
ConsumeToken.call(wf_case, end_place)
|
23
|
+
wf_case.finished!
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class FireMessageTransition
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise("Transition #{workitem.transition.name} is not message triggered") unless workitem.transition.message?
|
13
|
+
|
14
|
+
Wf::ApplicationRecord.transaction do
|
15
|
+
FireTransitionInternal.call(workitem)
|
16
|
+
SweepAutomaticTransitions.call(workitem.case)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class FireTransitionInternal
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
if workitem.enabled?
|
13
|
+
locked_item = nil
|
14
|
+
elsif workitem.started?
|
15
|
+
locked_item = workitem
|
16
|
+
else
|
17
|
+
raise("can not fire the transition if it is not in state enabled or started.")
|
18
|
+
end
|
19
|
+
Wf::ApplicationRecord.transaction do
|
20
|
+
workitem.update!(finished_at: Time.zone.now, state: :finished)
|
21
|
+
# TODO: only in?
|
22
|
+
workitem.transition.arcs.each do |arc|
|
23
|
+
ConsumeToken.call(workitem.case, arc.place, locked_item)
|
24
|
+
end
|
25
|
+
# last arc without guard -> pass
|
26
|
+
has_passed = false
|
27
|
+
workitem.transition.arcs.out.order("guards_count DESC").each do |arc|
|
28
|
+
if workitem.transition.explicit_or_split?
|
29
|
+
if workitem.pass_guard?(arc, has_passed)
|
30
|
+
has_passed = true
|
31
|
+
AddToken.call(workitem.case, arc.place)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
AddToken.call(workitem.case, arc.place)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
workitem.transition.fire_callback.constantize.new(workitem.id).perform_now
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class LockToken
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case, :place, :workitem
|
7
|
+
def initialize(wf_case, place, workitem)
|
8
|
+
@wf_case = wf_case
|
9
|
+
@place = place
|
10
|
+
@workitem = workitem
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
wf_case.tokens.free.where(place: place).limit(1).update_all(
|
15
|
+
state: :locked,
|
16
|
+
locked_at: Time.zone.now,
|
17
|
+
locked_workitem_id: workitem.id
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class New
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workflow, :target
|
7
|
+
def initialize(workflow, target = nil)
|
8
|
+
@workflow = workflow
|
9
|
+
@target = target
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
wf_case = workflow.cases.create!(targetable: target, state: :created)
|
14
|
+
wf_case
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class ReleaseToken
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
Wf::Token.where(locked_workitem_id: workitem.id).locked.each do |token|
|
14
|
+
AddToken.call(token.case, token.place)
|
15
|
+
token.update!(state: :canceled, canceled_at: Time.zone.now)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class RemoveManualAssignment
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case, :transition, :party
|
7
|
+
def initialize(wf_case, transition, party)
|
8
|
+
@wf_case = wf_case
|
9
|
+
@transition = transition
|
10
|
+
@party = party
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
wf_case.case_assignments.where(transition: transition, party: party).find_each(&:destroy)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class RemoveWorkitemAssignment
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem, :party, :permanent
|
7
|
+
def initialize(workitem, party, permanent = true)
|
8
|
+
@workitem = workitem
|
9
|
+
@party = party
|
10
|
+
@permanent = permanent
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
return if party.nil?
|
15
|
+
|
16
|
+
Wf::ApplicationRecord.transaction do
|
17
|
+
RemoveManualAssignment.call(workitem.case, workitem.transition, party) if permanent
|
18
|
+
workitem.workitem_assignments.where(party: party).first&.destroy
|
19
|
+
|
20
|
+
workitem.transition.unassignment_callback.constantize.new(workitem.id).perform_now if workitem.workitem_assignments.count == 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class Resume
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise("Only suspended or canceled cases can be resumed") unless wf_case.suspended? || wf_case.canceled?
|
13
|
+
|
14
|
+
wf_case.active!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class SetWorkitemAssignments
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem
|
7
|
+
def initialize(workitem)
|
8
|
+
@workitem = workitem
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
has_case_ass = false
|
14
|
+
workitem.case.case_assignments.where(transition: workitem.transition).find_each do |case_ass|
|
15
|
+
AddWorkitemAssignment.call(workitem, case_ass.party, false)
|
16
|
+
has_case_ass = true
|
17
|
+
end
|
18
|
+
|
19
|
+
unless has_case_ass
|
20
|
+
callback_values = workitem.transition.assignment_callback.constantize.new(workitem.id).perform
|
21
|
+
if callback_values.present?
|
22
|
+
# TODO: do assignment for callback.
|
23
|
+
else
|
24
|
+
workitem.transition.transition_static_assignments.each do |static_assignment|
|
25
|
+
AddWorkitemAssignment.call(workitem, static_assignment.party, false)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class StartCase
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
wf_case.active!
|
14
|
+
AddToken.call(wf_case, wf_case.workflow.places.start.first)
|
15
|
+
SweepAutomaticTransitions.call(wf_case)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class StartWorkitem
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem, :user
|
7
|
+
def initialize(workitem, user)
|
8
|
+
@workitem = workitem
|
9
|
+
@user = user
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
raise("The workitem is not in state #{workitem.state}") unless workitem.enabled?
|
14
|
+
|
15
|
+
# TODO: holding timeout
|
16
|
+
Wf::ApplicationRecord.transaction do
|
17
|
+
workitem.update!(state: :started, holding_user: user)
|
18
|
+
|
19
|
+
workitem.transition.arcs.in.each do |arc|
|
20
|
+
LockToken.call(workitem.case, arc.place, workitem)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
workitem
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class Suspend
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise("Only active or suspended cases can be canceled") unless wf_case.active?
|
13
|
+
|
14
|
+
wf_case.suspended!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class SweepAutomaticTransitions
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :wf_case
|
7
|
+
def initialize(wf_case)
|
8
|
+
@wf_case = wf_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
Wf::ApplicationRecord.transaction do
|
13
|
+
EnableTransitions.call(wf_case)
|
14
|
+
done = false
|
15
|
+
until done
|
16
|
+
done = true
|
17
|
+
finished = FinishedP.call(wf_case).result
|
18
|
+
next if finished
|
19
|
+
|
20
|
+
Wf::ApplicationRecord.uncached do
|
21
|
+
wf_case.workitems.joins(:transition).where(state: :enabled).where(Wf::Transition.table_name => { trigger_type: Wf::Transition.trigger_types[:automatic] }).find_each do |item|
|
22
|
+
FireTransitionInternal.call(item)
|
23
|
+
done = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
EnableTransitions.call(wf_case)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class SweepTimedTransitions
|
5
|
+
prepend SimpleCommand
|
6
|
+
|
7
|
+
def call
|
8
|
+
Wf::ApplicationRecord.transaction do
|
9
|
+
Wf::Workitem.enabled.where("trigger_time <= ?", Time.zone.now).find_each do |item|
|
10
|
+
FireTransitionInternal.call(item)
|
11
|
+
SweepAutomaticTransitions.call(item.case)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wf::CaseCommand
|
4
|
+
class WorkitemAction
|
5
|
+
prepend SimpleCommand
|
6
|
+
attr_reader :workitem, :action, :user
|
7
|
+
def initialize(workitem, user, action = :start)
|
8
|
+
@workitem = workitem
|
9
|
+
@action = action
|
10
|
+
@user = user
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
Wf::ApplicationRecord.transaction do
|
15
|
+
BeginWorkitemAction.call(workitem, user, action)
|
16
|
+
EndWorkitemAction.call(workitem, user, action)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# == Schema Information
|
3
|
+
#
|
4
|
+
# Table name: wf_comments
|
5
|
+
#
|
6
|
+
# id :integer not null, primary key
|
7
|
+
# workitem_id :integer
|
8
|
+
# user_id :string
|
9
|
+
# body :text
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
#
|
13
|
+
|
14
|
+
# frozen_string_literal: true
|
15
|
+
|
16
|
+
module Wf
|
17
|
+
class Comment < ApplicationRecord
|
18
|
+
belongs_to :workitem
|
19
|
+
belongs_to :user, class_name: Wf::Workflow.user_class.to_s
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: wf_demo_targets
|
6
|
+
#
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# name :string
|
9
|
+
# description :string
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
#
|
13
|
+
|
14
|
+
module Wf
|
15
|
+
class DemoTarget < ApplicationRecord
|
16
|
+
has_many :cases, as: :targetable
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: wf_entries
|
6
|
+
#
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# user_id :string
|
9
|
+
# workitem_id :integer
|
10
|
+
# payload :json default("{}")
|
11
|
+
# created_at :datetime not null
|
12
|
+
# updated_at :datetime not null
|
13
|
+
#
|
14
|
+
|
15
|
+
module Wf
|
16
|
+
class Entry < ApplicationRecord
|
17
|
+
belongs_to :user, class_name: Wf::Workflow.user_class.to_s
|
18
|
+
belongs_to :workitem
|
19
|
+
has_many :field_values
|
20
|
+
|
21
|
+
after_initialize do
|
22
|
+
self.payload = {} if payload.blank?
|
23
|
+
end
|
24
|
+
|
25
|
+
def json
|
26
|
+
field_values.includes(:field).map { |x| [x.field_id.to_i, { field_id: x.id.to_i, field_name: x.field.name, value: x.value_after_cast }] }.to_h
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_payload!
|
30
|
+
update(payload: json)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: wf_fields
|
6
|
+
#
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# name :string
|
9
|
+
# form_id :integer
|
10
|
+
# position :integer default("0")
|
11
|
+
# field_type :integer default("0")
|
12
|
+
# field_type_name :string
|
13
|
+
# default_value :string
|
14
|
+
# created_at :datetime not null
|
15
|
+
# updated_at :datetime not null
|
16
|
+
#
|
17
|
+
|
18
|
+
module Wf
|
19
|
+
class Field < ApplicationRecord
|
20
|
+
belongs_to :form, touch: true
|
21
|
+
|
22
|
+
enum field_type: {
|
23
|
+
string: 0,
|
24
|
+
integer: 1,
|
25
|
+
boolean: 2,
|
26
|
+
date: 3,
|
27
|
+
datetime: 4,
|
28
|
+
decimal: 5,
|
29
|
+
float: 6,
|
30
|
+
json: 7,
|
31
|
+
text: 8,
|
32
|
+
|
33
|
+
"string[]": 20,
|
34
|
+
"integer[]": 21,
|
35
|
+
"date[]": 23,
|
36
|
+
"datetime[]": 24,
|
37
|
+
"decimal[]": 25,
|
38
|
+
"float[]": 26,
|
39
|
+
"json[]": 27,
|
40
|
+
"text[]": 28
|
41
|
+
}
|
42
|
+
|
43
|
+
def type_for_cast
|
44
|
+
type = field_type.to_s.match(/^(\w+)(\[\])?$/)[1]
|
45
|
+
is_array = field_type.to_s.match(/^(\w+)(\[\])?$/)[2] == "[]"
|
46
|
+
if is_array
|
47
|
+
ActiveRecord::Type.lookup(type.to_sym, array: true)
|
48
|
+
else
|
49
|
+
ActiveRecord::Type.lookup(type.to_sym)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|