-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolves #15282 ### Description Adds CavcTask to be the parent for all CAVC-related tasks. This task blocks distribution until all its children and itself are completed. There are no actions available to any user for this task. ## Acceptance criteria - [x] Verify a new task of type "CavcTask" model is created - [x] Verify the task ~is~ [can only be] a child of a distribution task on the appeal - [x] Verify task is completed when all of its children are completed/cancelled - [x] Verify label reads "All CAVC related tasks" - [x] Verify the task is Assigned to Bva ### Testing Plan ```ruby # Find an appeal with an open DistributionTask to play with appeal=DistributionTask.open.first.appeal appeal.treee ┌──────────────────────────────────────────────────────────────┐ Appeal 11 (evidence_submission) ──────── │ ID │ STATUS │ ASGN_BY │ ASGN_TO │ UPDATED_AT │ └── RootTask │ 24 │ on_hold │ │ Bva │ 2020-09-22 22:46:52 UTC │ └── DistributionTask │ 25 │ on_hold │ │ Bva │ 2020-09-22 22:46:52 UTC │ └── EvidenceSubmissionWindowTask │ 26 │ assigned │ │ MailTeam │ 2020-09-22 22:46:52 UTC │ └──────────────────────────────────────────────────────────────┘ c=CavcTask.create(appeal: appeal, parent: appeal.root_task) # should fail because parent should be a DistributionTask appeal.reload.treee parent_task=appeal.tasks.open.where(type: DistributionTask.name).first t=CavcTask.create(appeal: appeal, parent: parent_task) appeal.reload.treee t.assigned_to t.label t.available_actions(nil) # argument is not used # create child tasks (as many as you want) child_task=TranslationTask.create(appeal: appeal, parent: t, assigned_to: User.all.sample) appeal.reload.treee child_task.cancelled! appeal.reload.treee t.reload.cancelled? t.reload.closed? # repeat the above except complete the child_task instead child_task.completed! ``` ### Code Documentation Updates - [x] Add or update code comments at the top of the class, module, and/or component.
- Loading branch information
Showing
6 changed files
with
200 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# frozen_string_literal: true | ||
|
||
## | ||
# This task is used to track all related CAVC subtasks for AMA Appeal Streams. | ||
# If this task is still open, there is still more CAVC-specific work to be done of this appeal. | ||
# This task should be a child of DistributionTask, and so it blocks distribution until all its children are closed. | ||
# There are no actions available to any user for this task. | ||
|
||
class CavcTask < Task | ||
validates :parent, presence: true, parentTask: { task_type: DistributionTask }, on: :create | ||
|
||
before_validation :set_assignee | ||
|
||
def self.label | ||
"All CAVC-related tasks" | ||
end | ||
|
||
def default_instructions | ||
[COPY::CAVC_TASK_DEFAULT_INSTRUCTIONS] | ||
end | ||
|
||
def available_actions(_user) | ||
[] | ||
end | ||
|
||
def verify_org_task_unique | ||
true | ||
end | ||
|
||
private | ||
|
||
def set_assignee | ||
self.assigned_to = Bva.singleton | ||
end | ||
|
||
def cascade_closure_from_child_task?(_child_task) | ||
true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
## | ||
# Validates the parent task | ||
# | ||
# Usage example: For the parent field, calls the built-in PresenceValidator and | ||
# ParentTaskValidator with argument DistributionTask when the record is being created: | ||
# validates :parent, presence: true, parentTask: { task_type: DistributionTask }, on: :create | ||
|
||
class ParentTaskValidator < ActiveModel::Validator | ||
def validate(record) | ||
record.errors.add(:parent, "parent should be a #{options[:task_type].name}") unless correct_parent_type?(record) | ||
end | ||
|
||
private | ||
|
||
def correct_parent_type?(record) | ||
return true if options[:task_type].nil? | ||
|
||
record.parent&.type == options[:task_type].name | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# frozen_string_literal: true | ||
|
||
describe CavcTask, :postgres do | ||
describe ".create" do | ||
subject { described_class.create(appeal: appeal, parent: parent_task) } | ||
let(:appeal) { create(:appeal) } | ||
let!(:parent_task) { create(:distribution_task, appeal: appeal) } | ||
|
||
context "parent is DistributionTask" do | ||
it "creates task" do | ||
new_task = subject | ||
expect(new_task.valid?) | ||
expect(new_task.errors.messages[:parent]).to be_empty | ||
|
||
expect(appeal.tasks).to include new_task | ||
expect(parent_task.children).to include new_task | ||
|
||
expect(new_task.assigned_to).to eq Bva.singleton | ||
expect(new_task.label).to eq "All CAVC-related tasks" | ||
expect(new_task.default_instructions).to eq [COPY::CAVC_TASK_DEFAULT_INSTRUCTIONS] | ||
end | ||
end | ||
|
||
context "parent is not a DistributionTask" do | ||
let(:parent_task) { create(:root_task) } | ||
it "fails to create task" do | ||
new_task = subject | ||
expect(new_task.invalid?) | ||
expect(new_task.errors.messages[:parent]).to include("parent should be a DistributionTask") | ||
end | ||
end | ||
|
||
context "parent is nil" do | ||
let(:parent_task) { nil } | ||
it "fails to create task" do | ||
new_task = subject | ||
expect(new_task.invalid?) | ||
expect(new_task.errors.messages[:parent]).to include("can't be blank") | ||
end | ||
end | ||
end | ||
|
||
describe "FactoryBot.create(:cavc_task) with different arguments" do | ||
context "appeal is provided" do | ||
let(:appeal) { create(:appeal) } | ||
let!(:parent_task) { create(:distribution_task, appeal: appeal) } | ||
let!(:cavc_task) { create(:cavc_task, appeal: appeal) } | ||
it "finds existing distribution_task to use as parent" do | ||
expect(Appeal.count).to eq 1 | ||
expect(RootTask.count).to eq 1 | ||
expect(DistributionTask.count).to eq 1 | ||
expect(CavcTask.count).to eq 1 | ||
end | ||
end | ||
context "parent task is provided" do | ||
let(:parent_task) { create(:distribution_task) } | ||
let!(:cavc_task) { create(:cavc_task, parent: parent_task) } | ||
it "uses existing distribution_task" do | ||
expect(Appeal.count).to eq 1 | ||
expect(RootTask.count).to eq 1 | ||
expect(DistributionTask.count).to eq 1 | ||
expect(CavcTask.count).to eq 1 | ||
end | ||
end | ||
context "nothing is provided" do | ||
let!(:cavc_task) { create(:cavc_task) } | ||
it "creates realistic task tree" do | ||
expect(Appeal.count).to eq 1 | ||
expect(RootTask.count).to eq 1 | ||
expect(DistributionTask.count).to eq 1 | ||
expect(CavcTask.count).to eq 1 | ||
end | ||
end | ||
end | ||
|
||
describe "#available_actions" do | ||
let(:user) { create(:user) } | ||
let(:cavc_task) { create(:cavc_task) } | ||
it "returns empty" do | ||
expect(cavc_task.available_actions(user)).to be_empty | ||
end | ||
end | ||
|
||
context "closing child tasks" do | ||
let(:user) { create(:user) } | ||
let(:cavc_task) { create(:cavc_task) } | ||
let!(:child_task) { create(:ama_task, parent: cavc_task) } | ||
context "as complete" do | ||
it "completes parent CavcTask" do | ||
child_task.completed! | ||
expect(cavc_task.closed?) | ||
expect(cavc_task.status).to eq "completed" | ||
end | ||
end | ||
context "as cancelled" do | ||
it "cancels parent CavcTask" do | ||
child_task.cancelled! | ||
expect(cavc_task.closed?) | ||
expect(cavc_task.status).to eq "cancelled" | ||
end | ||
end | ||
context "has multiple children" do | ||
let!(:child_task2) { create(:ama_task, parent: cavc_task) } | ||
it "leaves parent CavcTask open when completing 1 child" do | ||
child_task.completed! | ||
expect(cavc_task.open?) | ||
expect(cavc_task.status).to eq "on_hold" | ||
end | ||
it "leaves parent CavcTask open when cancelling 1 child" do | ||
child_task.cancelled! | ||
expect(cavc_task.open?) | ||
expect(cavc_task.status).to eq "on_hold" | ||
end | ||
it "closes parent CavcTask when closing last open child" do | ||
child_task.cancelled! | ||
expect(cavc_task.open?) | ||
expect(cavc_task.status).to eq "on_hold" | ||
child_task2.completed! | ||
expect(cavc_task.closed?) | ||
expect(cavc_task.status).to eq "completed" | ||
end | ||
end | ||
end | ||
end |