diff --git a/packages/distribution/addon/abilities/inquiry.js b/packages/distribution/addon/abilities/inquiry.js
index 445b97c52..e2e130800 100644
--- a/packages/distribution/addon/abilities/inquiry.js
+++ b/packages/distribution/addon/abilities/inquiry.js
@@ -56,4 +56,14 @@ export default class InquiryAbility extends Ability {
) ?? true
);
}
+
+ get canReopen() {
+ return (
+ this.model.isRedoable &&
+ this.model?.addressedGroups
+ .map(String)
+ .includes(String(this.calumaOptions.currentGroupId)) &&
+ (this.config.permissions.reopenInquiry?.(this.model) ?? true)
+ );
+ }
}
diff --git a/packages/distribution/addon/components/cd-inquiry-dialog.js b/packages/distribution/addon/components/cd-inquiry-dialog.js
index 1bfd36110..35ecd28e5 100644
--- a/packages/distribution/addon/components/cd-inquiry-dialog.js
+++ b/packages/distribution/addon/components/cd-inquiry-dialog.js
@@ -52,6 +52,8 @@ export default class CdInquiryDialogComponent extends Component {
},
});
+ this._setRedoableStates(response.allWorkItems);
+
/**
* Sadly this is necessary to handle what happens after the withdraw task in
* the inquiry part component because the mutation triggers a refresh of the
@@ -68,11 +70,39 @@ export default class CdInquiryDialogComponent extends Component {
if (allWorkItems.edges.every((edge) => edge.node.status === "CANCELED")) {
this.router.transitionTo("index");
}
+
+ /**
+ * Get work item that was redoable in the previous calulation and is now
+ * not anymore. This indicates that the work item was redone which should
+ * result in a transition to the answer view.
+ */
+ const redoneWorkItem = this._redoableStates.find((stateObj) => {
+ const updatedWorkItem = allWorkItems.edges.find(
+ (edge) => decodeId(edge.node.id) === stateObj.id
+ );
+
+ return (
+ stateObj.isRedoable && !(updatedWorkItem?.node.isRedoable ?? true)
+ );
+ });
+
+ if (redoneWorkItem) {
+ this.router.transitionTo("inquiry.detail.answer", redoneWorkItem.id);
+ }
+
+ this._setRedoableStates(allWorkItems);
});
return response;
}
+ _setRedoableStates(allWorkItems) {
+ this._redoableStates = allWorkItems.edges.map((edge) => ({
+ id: decodeId(edge.node.id),
+ isRedoable: edge.node.isRedoable,
+ }));
+ }
+
@dropTask
*createInquiry(e) {
e.preventDefault();
diff --git a/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.hbs b/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.hbs
index d5b3cc748..71d042a4b 100644
--- a/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.hbs
+++ b/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.hbs
@@ -77,6 +77,13 @@
{{/if}}
+ {{#if (and (eq @type "answer") (can "reopen inquiry" @inquiry))}}
+
+
+ {{t "caluma.distribution.reopen-inquiry.link"}}
+
+
+ {{/if}}
{{/unless}}
diff --git a/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.js b/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.js
index 2ec89b227..7cd00feda 100644
--- a/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.js
+++ b/packages/distribution/addon/components/cd-inquiry-dialog/inquiry-part.js
@@ -7,6 +7,7 @@ import { confirm } from "ember-uikit";
import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
import config from "@projectcaluma/ember-distribution/config";
+import reopenInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/reopen-inquiry.graphql";
import withdrawInquiryMutation from "@projectcaluma/ember-distribution/gql/mutations/withdraw-inquiry.graphql";
import inquiryAnswerStatus from "@projectcaluma/ember-distribution/utils/inquiry-answer-status";
@@ -73,4 +74,33 @@ export default class CdInquiryDialogInquiryPartComponent extends Component {
);
}
}
+
+ @dropTask
+ *reopen(e) {
+ e.preventDefault();
+
+ /* istanbul ignore next */
+ if (
+ !(yield confirm(
+ this.intl.t("caluma.distribution.reopen-inquiry.confirm")
+ ))
+ ) {
+ return;
+ }
+
+ try {
+ yield this.apollo.mutate({
+ mutation: reopenInquiryMutation,
+ variables: {
+ workItem: decodeId(this.args.inquiry.id),
+ statusQuestion: this.config.inquiry.answer.statusQuestion,
+ buttonTasks: Object.keys(this.config.inquiry.answer.buttons),
+ },
+ });
+ } catch (error) {
+ this.notification.danger(
+ this.intl.t("caluma.distribution.reopen-inquiry.error")
+ );
+ }
+ }
}
diff --git a/packages/distribution/addon/components/cd-navigation/controls.js b/packages/distribution/addon/components/cd-navigation/controls.js
index 44f69194d..b69cf143e 100644
--- a/packages/distribution/addon/components/cd-navigation/controls.js
+++ b/packages/distribution/addon/components/cd-navigation/controls.js
@@ -8,7 +8,7 @@ import { gql } from "graphql-tag";
import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
import config from "@projectcaluma/ember-distribution/config";
import completeWorkItemMutation from "@projectcaluma/ember-distribution/gql/mutations/complete-work-item.graphql";
-import redoWorkItemMutation from "@projectcaluma/ember-distribution/gql/mutations/redo-work-item.graphql";
+import reopenDistributionMutation from "@projectcaluma/ember-distribution/gql/mutations/reopen-distribution.graphql";
import incompleteInquiriesQuery from "@projectcaluma/ember-distribution/gql/queries/incomplete-inquiries.graphql";
export default class CdNavigationControlsComponent extends Component {
@@ -76,7 +76,7 @@ export default class CdNavigationControlsComponent extends Component {
);
yield this.apollo.mutate({
- mutation: redoWorkItemMutation,
+ mutation: reopenDistributionMutation,
variables: {
workItem: distributionWorkItemId,
},
diff --git a/packages/distribution/addon/gql/fragments/inquiry.graphql b/packages/distribution/addon/gql/fragments/inquiry.graphql
index 86c6134eb..b3a8df84b 100644
--- a/packages/distribution/addon/gql/fragments/inquiry.graphql
+++ b/packages/distribution/addon/gql/fragments/inquiry.graphql
@@ -67,6 +67,7 @@ fragment InquiryDialog on WorkItem {
createdAt
closedAt
status
+ isRedoable
task {
id
slug
diff --git a/packages/distribution/addon/gql/mutations/complete-inquiry-work-item.graphql b/packages/distribution/addon/gql/mutations/complete-inquiry-work-item.graphql
index 7c4ea2a78..7a00df92e 100644
--- a/packages/distribution/addon/gql/mutations/complete-inquiry-work-item.graphql
+++ b/packages/distribution/addon/gql/mutations/complete-inquiry-work-item.graphql
@@ -29,6 +29,7 @@ mutation CompleteInquiryWorkItem(
parentWorkItem {
id
status
+ isRedoable
}
}
}
diff --git a/packages/distribution/addon/gql/mutations/redo-work-item.graphql b/packages/distribution/addon/gql/mutations/reopen-distribution.graphql
similarity index 67%
rename from packages/distribution/addon/gql/mutations/redo-work-item.graphql
rename to packages/distribution/addon/gql/mutations/reopen-distribution.graphql
index d0559a4c7..945e97143 100644
--- a/packages/distribution/addon/gql/mutations/redo-work-item.graphql
+++ b/packages/distribution/addon/gql/mutations/reopen-distribution.graphql
@@ -1,4 +1,4 @@
-mutation RedoWorkItem($workItem: ID!) {
+mutation ReopenDistribution($workItem: ID!) {
redoWorkItem(input: { id: $workItem }) {
workItem {
id
diff --git a/packages/distribution/addon/gql/mutations/reopen-inquiry.graphql b/packages/distribution/addon/gql/mutations/reopen-inquiry.graphql
new file mode 100644
index 000000000..c97876d88
--- /dev/null
+++ b/packages/distribution/addon/gql/mutations/reopen-inquiry.graphql
@@ -0,0 +1,33 @@
+#import InquiryStatusDocument from '../fragments/inquiry.graphql'
+
+mutation ReopenInquiry(
+ $workItem: ID!
+ $statusQuestion: ID!
+ $buttonTasks: [String]!
+) {
+ redoWorkItem(input: { id: $workItem }) {
+ workItem {
+ id
+ status
+ isRedoable
+ childCase {
+ id
+ document {
+ id
+ ...InquiryStatusDocument
+ }
+ workItems(filter: [{ tasks: $buttonTasks }, { status: READY }]) {
+ edges {
+ node {
+ id
+ task {
+ id
+ slug
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/distribution/tests/integration/components/cd-inquiry-dialog-test.js b/packages/distribution/tests/integration/components/cd-inquiry-dialog-test.js
index c337ea9fb..17a87d8d5 100644
--- a/packages/distribution/tests/integration/components/cd-inquiry-dialog-test.js
+++ b/packages/distribution/tests/integration/components/cd-inquiry-dialog-test.js
@@ -130,4 +130,38 @@ module("Integration | Component | cd-inquiry-dialog", function (hooks) {
assert.verifySteps(["transition"]);
});
+
+ test("it can reopen an inquiry", async function (assert) {
+ assert.expect(6);
+
+ const inquiry = confirmInquiry({
+ inquiry: answerInquiry(this.server, {
+ inquiry: sendInquiry(this.server, {
+ inquiry: createInquiry(this.server, this.distributionCase, {
+ from: { id: "group2" },
+ to: { id: "group1" },
+ }),
+ }),
+ }),
+ });
+
+ assert.strictEqual(inquiry.status, "COMPLETED");
+
+ await render(
+ hbs``
+ );
+
+ this.owner.lookup("service:router").transitionTo = (route, id) => {
+ assert.strictEqual(route, "inquiry.detail.answer");
+ assert.strictEqual(id, inquiry.id);
+ assert.step("transition");
+ };
+
+ await click("[data-test-reopen]");
+ await confirm();
+
+ assert.strictEqual(inquiry.status, "READY");
+
+ assert.verifySteps(["transition"]);
+ });
});
diff --git a/packages/distribution/tests/integration/components/cd-navigation/controls-test.js b/packages/distribution/tests/integration/components/cd-navigation/controls-test.js
index 97e1c4989..fe0e3fb06 100644
--- a/packages/distribution/tests/integration/components/cd-navigation/controls-test.js
+++ b/packages/distribution/tests/integration/components/cd-navigation/controls-test.js
@@ -95,7 +95,7 @@ module("Integration | Component | cd-navigation/controls", function (hooks) {
);
});
- test("it can redo the current distribution", async function (assert) {
+ test("it can reopen the current distribution", async function (assert) {
await assert.expect(3);
await render(hbs``);
diff --git a/packages/distribution/translations/de.yaml b/packages/distribution/translations/de.yaml
index bf3c744f5..7f6bca5b8 100644
--- a/packages/distribution/translations/de.yaml
+++ b/packages/distribution/translations/de.yaml
@@ -85,3 +85,8 @@ caluma:
confirm: "Wollen Sie die Anfrage wirklich zurückziehen?"
error: "Fehler beim Zurückziehen der Anfrage"
status: "Zurückgezogen"
+
+ reopen-inquiry:
+ link: "Wiedereröffnen"
+ confirm: "Wollen Sie die Anfrage wirklich wiedereröffnen?"
+ error: "Fehler beim Wiedereröffnen der Anfrage"
diff --git a/packages/distribution/translations/en.yaml b/packages/distribution/translations/en.yaml
index e2900b843..3b92533a6 100644
--- a/packages/distribution/translations/en.yaml
+++ b/packages/distribution/translations/en.yaml
@@ -86,3 +86,8 @@ caluma:
confirm: "Do you really want to withdraw the inquiry?"
error: "Error while withdrawing the inquiry"
status: "Withdrawn"
+
+ reopen-inquiry:
+ link: "Reopen"
+ confirm: "Do you really want to reopen the inquiry?"
+ error: "Error while reopening the inquiry"
diff --git a/packages/distribution/translations/fr.yaml b/packages/distribution/translations/fr.yaml
index ba9949a56..80d8f32bb 100644
--- a/packages/distribution/translations/fr.yaml
+++ b/packages/distribution/translations/fr.yaml
@@ -85,3 +85,8 @@ caluma:
confirm: "Voulez-vous vraiment retirer la demande ?"
error: "Erreur lors du retrait de la demande"
status: "Retirée"
+
+ reopen-inquiry:
+ link: "Rouvrir"
+ confirm: "Voulez-vous vraiment rouvrir la demande ?"
+ error: "Erreur lors de la réouverture de la demande"
diff --git a/packages/testing/addon/mirage-graphql/mocks/work-item.js b/packages/testing/addon/mirage-graphql/mocks/work-item.js
index 57875a442..c8f38900f 100644
--- a/packages/testing/addon/mirage-graphql/mocks/work-item.js
+++ b/packages/testing/addon/mirage-graphql/mocks/work-item.js
@@ -31,16 +31,21 @@ export default class WorkItemMock extends BaseMock {
handleRedoWorkItem(_, { input }) {
const { id } = deserialize(input);
const workItem = this.collection.find(id);
+ const caseId = workItem?.childCaseId;
if (workItem.taskId === "distribution") {
- const caseId = workItem.childCaseId;
-
this.collection
.where({ caseId, taskId: "complete-distribution" })
.update({ status: "READY" });
this.collection
.where({ caseId, taskId: "create-inquiry" })
.update({ status: "READY" });
+ } else if (workItem.taskId === "inquiry") {
+ this.server.create("work-item", {
+ caseId,
+ status: "READY",
+ taskId: "adjust-inquiry-answer",
+ });
}
return this.handleSavePayload.fn.call(this, _, {
@@ -81,7 +86,7 @@ export default class WorkItemMock extends BaseMock {
.update({ status: "CANCELED" });
this.collection
.findBy({ childCaseId: caseId })
- .update({ status: "COMPLETED" });
+ .update({ status: "COMPLETED", isRedoable: true });
this.schema.cases.find(caseId).update({ status: "COMPLETED" });
} else if (taskId === "revise-inquiry-answer") {
this.collection
diff --git a/packages/testing/addon/scenarios/distribution.js b/packages/testing/addon/scenarios/distribution.js
index 6e92f2516..42190a72f 100644
--- a/packages/testing/addon/scenarios/distribution.js
+++ b/packages/testing/addon/scenarios/distribution.js
@@ -193,7 +193,7 @@ export function answerInquiry(server, { inquiry, status, reason, hint }) {
}
export function confirmInquiry({ inquiry }) {
- inquiry.update({ status: "COMPLETED" });
+ inquiry.update({ status: "COMPLETED", isRedoable: true });
inquiry.childCase.update({
status: "COMPLETED",
closedAt: faker.date.recent(),