@smartkomm/plexus-cli 0.0.0-stage → 0.1.1
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.
- package/README.md +863 -2
- package/dist/cli.mjs +5432 -0
- package/dist/skill/.managed-by-plexus-cli +1 -0
- package/dist/skill/SKILL.md +224 -0
- package/dist/skill/references/accounts/email-changes.md +46 -0
- package/dist/skill/references/agents/use-shared-tools.md +52 -0
- package/dist/skill/references/applications/inspect-process-store.md +61 -0
- package/dist/skill/references/applications/start-a-test-application.md +66 -0
- package/dist/skill/references/audit/answer-access-request.md +115 -0
- package/dist/skill/references/config/attach-a-template.md +117 -0
- package/dist/skill/references/config/init-tenant.md +121 -0
- package/dist/skill/references/config/onboard-tenant.md +71 -0
- package/dist/skill/references/config/rename-program-stage.md +99 -0
- package/dist/skill/references/config/set-tenant-branding.md +150 -0
- package/dist/skill/references/config/set-tenant-terms.md +50 -0
- package/dist/skill/references/config/set-up-billing-catalog.md +73 -0
- package/dist/skill/references/config/update-tenant-config.md +174 -0
- package/dist/skill/references/config/wipe-tenant-config.md +107 -0
- package/dist/skill/references/export/create-named-export.md +47 -0
- package/dist/skill/references/feedback/create-and-triage-feedback.md +69 -0
- package/dist/skill/references/feedback/manage-feedback-tags.md +57 -0
- package/dist/skill/references/finance/change-contract-grant.md +36 -0
- package/dist/skill/references/finance/record-submission-date.md +33 -0
- package/dist/skill/references/interessenten/list-interessenten.md +54 -0
- package/dist/skill/references/marketing/demo-video-links.md +101 -0
- package/dist/skill/references/notifications/debug-mail-delivery.md +77 -0
- package/dist/skill/references/notifications/mail-level.md +90 -0
- package/dist/skill/references/notifications/reword-a-letter.md +155 -0
- package/dist/skill/references/notifications/trace-a-login.md +50 -0
- package/dist/skill/references/offer/add-workflow-node.md +268 -0
- package/dist/skill/references/offer/addresses.md +129 -0
- package/dist/skill/references/offer/appointment-task.md +79 -0
- package/dist/skill/references/offer/assignment-rule.md +195 -0
- package/dist/skill/references/offer/attach-form-to-workflow.md +79 -0
- package/dist/skill/references/offer/author-form-scenarios.md +97 -0
- package/dist/skill/references/offer/author-manifest-meta.md +94 -0
- package/dist/skill/references/offer/author-smartform.md +102 -0
- package/dist/skill/references/offer/bind-node-input.md +76 -0
- package/dist/skill/references/offer/completeness-check.md +137 -0
- package/dist/skill/references/offer/countersign-node.md +91 -0
- package/dist/skill/references/offer/create-pedagogy-unit.md +55 -0
- package/dist/skill/references/offer/declare-node-reads.md +99 -0
- package/dist/skill/references/offer/edit-live-tenant-offer.md +144 -0
- package/dist/skill/references/offer/edit-smartform.md +121 -0
- package/dist/skill/references/offer/edit-workflow-node.md +126 -0
- package/dist/skill/references/offer/engage-push-node.md +147 -0
- package/dist/skill/references/offer/insert-and-rewire-node.md +67 -0
- package/dist/skill/references/offer/node-tasks.md +162 -0
- package/dist/skill/references/offer/optional-assessment.md +65 -0
- package/dist/skill/references/offer/publish-offer-bundle.md +117 -0
- package/dist/skill/references/offer/set-offer-capacities.md +78 -0
- package/dist/skill/references/offer/staff-input-if-node.md +112 -0
- package/dist/skill/references/offer/task-appointment-result.md +69 -0
- package/dist/skill/references/offer/task-family-request.md +69 -0
- package/dist/skill/references/offer/task-result-files.md +52 -0
- package/dist/skill/references/offer/template-document-node.md +113 -0
- package/dist/skill/references/offer/workflow-default-channels.md +69 -0
- package/dist/skill/references/resolver/manage-contract-resolver.md +161 -0
- package/dist/skill/references/retention/erase-due-applications.md +99 -0
- package/dist/skill/references/retention/erase-due-parties.md +107 -0
- package/dist/skill/references/roles/migrate-parent-assignments.md +31 -0
- package/dist/skill/references/signing/README.md +113 -0
- package/dist/skill/references/signing/connect-a-school.md +90 -0
- package/dist/skill/references/signing/rotate-the-key.md +41 -0
- package/dist/skill/references/stammdaten/purge-deleted-person.md +68 -0
- package/dist/skill/references/stripe/connect-a-school.md +107 -0
- package/dist/skill/references/stripe/request-and-verify-a-payment.md +78 -0
- package/dist/skill/references/test-actions/drive-a-test-application.md +69 -0
- package/dist/skill/references/users/add-platform-admin.md +59 -0
- package/dist/skill/references/users/add-platform-user.md +59 -0
- package/dist/skill/references/users/add-tenant-admin.md +75 -0
- package/dist/skill/references/users/change-login-email.md +55 -0
- package/dist/skill/references/users/cli-access-for-tenant-admin.md +117 -0
- package/dist/skill/references/users/delete-permission-group.md +76 -0
- package/dist/skill/references/users/grant-cross-tenant-access.md +57 -0
- package/dist/skill/references/users/grant-feedback-assignable.md +43 -0
- package/dist/skill/references/users/set-password.md +57 -0
- package/dist/skill/references/users/use-test-account.md +79 -0
- package/dist/skill/references/worker-ops/debug-worker-jobs.md +90 -0
- package/dist/skill/references/worker-ops/verify-migrations.md +51 -0
- package/dist/spec.snapshot.json +156821 -0
- package/package.json +53 -4
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Edit a workflow node
|
|
2
|
+
|
|
3
|
+
**When to use:** change an existing node in an offer's workflow — relabel it, change
|
|
4
|
+
who decides on a decision node, rebind a form node to a different
|
|
5
|
+
SmartForm, or rewire where an outcome routes — without removing and re-adding it.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
- An offer bundle on disk carrying a `workflow.json` (`offer init …` or `offer export …`).
|
|
9
|
+
- Authoring is **fully offline**; only `offer apply --publish` needs an API token of a
|
|
10
|
+
user who may configure the tenant's offers (a tenant admin — see
|
|
11
|
+
[Add a tenant admin](../users/add-tenant-admin.md)).
|
|
12
|
+
- An installed, current `plexus-cli` (`plexus-cli offer workflow node set --help`).
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
```bash
|
|
16
|
+
# Relabel a node — its label is ONE { de, en } field. A German-only change
|
|
17
|
+
# refuses while a real English exists (pass --label-en too); --label-en alone
|
|
18
|
+
# re-translates the current German.
|
|
19
|
+
plexus-cli offer workflow node set --dir <bundle> --id form --label "Bewerbungsformular" --label-en "Application form"
|
|
20
|
+
|
|
21
|
+
# Decision node: hand the decision row to another team (permission-group key) and
|
|
22
|
+
# name the outcomes that need a comment (there are no approver slots).
|
|
23
|
+
plexus-cli offer workflow node set --dir <bundle> --id freigabe \
|
|
24
|
+
--assign-decision schulleitung --comment-required rejected
|
|
25
|
+
|
|
26
|
+
# Form node: rebind to a different carried SmartForm.
|
|
27
|
+
plexus-cli offer workflow node set --dir <bundle> --id form --form <other-form-slug>
|
|
28
|
+
|
|
29
|
+
# Rewire routing: send an outcome to a different existing node.
|
|
30
|
+
plexus-cli offer workflow node set --dir <bundle> --id form --outcomes "standard:freigabe"
|
|
31
|
+
|
|
32
|
+
# End node: re-author the terminal outcome (re-syncs the terminal progress column).
|
|
33
|
+
plexus-cli offer workflow node set --dir <bundle> --id endRejected --outcome rejected
|
|
34
|
+
|
|
35
|
+
# End node: keep or discard the application's data at this end. Changing
|
|
36
|
+
# --outcome never changes it; a node without one must be given it here.
|
|
37
|
+
plexus-cli offer workflow node set --dir <bundle> --id endRejected --data-decision discard
|
|
38
|
+
|
|
39
|
+
# roleAssign node: change the granted role / mode; the person is an address.
|
|
40
|
+
plexus-cli offer workflow node set --dir <bundle> --id roleAssignSchueler --role schueler --mode add \
|
|
41
|
+
--person '$node.form.admission.beneficiary'
|
|
42
|
+
|
|
43
|
+
# What a node reads is named by address (single quotes — the shell expands $):
|
|
44
|
+
# setFlag: the instance it raises the flag on; countersign / engagePush: the
|
|
45
|
+
# contract; engagePush: the payment; a resolver contract / engagePush: the form
|
|
46
|
+
# instance (`--form` takes a SmartForm slug only on a FORM node).
|
|
47
|
+
plexus-cli offer workflow node set --dir <bundle> --id setFlagZusage --target '$node.form.admission'
|
|
48
|
+
plexus-cli offer workflow node set --dir <bundle> --id gegenzeichnung --contract '$node.contract.contract'
|
|
49
|
+
plexus-cli offer workflow node set --dir <bundle> --id contract --form '$node.form.admission'
|
|
50
|
+
plexus-cli offer workflow node set --dir <bundle> --id engagePush --payment '$node.zahlung.payment'
|
|
51
|
+
# A bare key is refused with the addresses visible at the node — see
|
|
52
|
+
# [Name what a node reads](./addresses.md). Check the result with
|
|
53
|
+
# plexus-cli offer workflow node reads --dir <bundle> --node <id>
|
|
54
|
+
|
|
55
|
+
# Document node (governedDocument): contract without a Freigabe, asking before it
|
|
56
|
+
# goes out („„Vertrag" jetzt senden?" on „Bereitstellen"). `--approval none` drops
|
|
57
|
+
# assign.releaseApproval + titles.approve; `--approval release` restores a
|
|
58
|
+
# Freigabe (title via --approve-title, default "<Dokument> freigeben") and drops
|
|
59
|
+
# the confirmation. Same edits as the IDE's Knotendetails → Einstellungen.
|
|
60
|
+
plexus-cli offer workflow node set --dir <bundle> --id contract --approval none --confirm-issue true
|
|
61
|
+
|
|
62
|
+
# Document node that the family returns signed (signedUpload / signedUploadChecked):
|
|
63
|
+
# „Bestätigung der Vertragsbedingungen" is ON by default — before the
|
|
64
|
+
# signed copy is uploaded the uploader confirms the terms, the protocol records
|
|
65
|
+
# who and when. Switch it off, or reword the question in BOTH languages
|
|
66
|
+
# ("" "" restores the default wording):
|
|
67
|
+
plexus-cli offer workflow node set --dir <bundle> --id contract --confirm-terms false
|
|
68
|
+
plexus-cli offer workflow node set --dir <bundle> --id contract \
|
|
69
|
+
--terms-question-de "Haben Sie den Schulvertrag gelesen und verstanden?" \
|
|
70
|
+
--terms-question-en "Have you read and understood the school contract?"
|
|
71
|
+
|
|
72
|
+
# Decision node: no outcome until ONE of its optional actions is COMPLETED —
|
|
73
|
+
# e.g. „Interview oder Taster Day vor der Grundsatzentscheidung". The keys are
|
|
74
|
+
# `optionalActions` keys of THIS node (add the actions first); a foreign or
|
|
75
|
+
# unknown key fails the publish gate ([decision/requiresOneOfUnknownAction]).
|
|
76
|
+
# `--requires-one-of ""` drops the rule. Only on `node set`: the actions must exist.
|
|
77
|
+
plexus-cli offer workflow node set --dir <bundle> --id decision --requires-one-of interview,tasterDay
|
|
78
|
+
|
|
79
|
+
# Then validate + publish (publishing re-versions the workflow).
|
|
80
|
+
plexus-cli offer validate --dir <bundle>
|
|
81
|
+
plexus-cli --env <env> offer apply --publish --dir <bundle>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Verify
|
|
85
|
+
```bash
|
|
86
|
+
plexus-cli offer workflow node list --dir <bundle> # label / outcomes / routing reflect the edit
|
|
87
|
+
plexus-cli offer validate --dir <bundle> # "local validation clean"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Idempotency / gotchas
|
|
91
|
+
- **Validate-before-write.** Every `node set` runs the real publish gate before
|
|
92
|
+
touching disk — on any error (bad routing target, unknown outcome, …) it
|
|
93
|
+
writes **nothing**.
|
|
94
|
+
- **A bundle exported before addresses were introduced is refused** (`[graph/retiredField]`: `wires`, a binding
|
|
95
|
+
with `path`, `adoptForm: true`) — export it again; never patch it by hand.
|
|
96
|
+
- **`--type` is not editable.** A type change rewires outcomes/specs/progress, so it is
|
|
97
|
+
a remove + add: `offer workflow node rm` then `offer workflow node add`. Passing
|
|
98
|
+
`--type` to `set` fails loud with that guidance.
|
|
99
|
+
- **Routing is validated at the boundary:** the outcome must be one the node declares
|
|
100
|
+
(or the implicit `done` for a no-outcome node), and the target must be an existing
|
|
101
|
+
node id — else it fails loud and writes nothing.
|
|
102
|
+
- **Approver group existence is server-side.** The CLI authors the
|
|
103
|
+
`permissionGroupKey`; whether it resolves to a real tenant permission group is checked
|
|
104
|
+
at `apply --publish` / runtime, not offline.
|
|
105
|
+
- **Relabel never touches progress.** Progress state/column labels come from the node's
|
|
106
|
+
events, not its label, so a `set` leaves the progress layout/wiring untouched.
|
|
107
|
+
- **`--confirm-issue true` needs approval `none`.** With a Freigabe, „Freigabe
|
|
108
|
+
anfordern" sends nothing to the family and the Freigabe is itself the check — the
|
|
109
|
+
flag would be dead wiring, so the CLI refuses it (and publish would too).
|
|
110
|
+
- **`--confirm-terms` / `--terms-question-*` only on a signing node.** A `confirm`
|
|
111
|
+
document (Platzangebot) has no signed copy to upload — the CLI refuses it, publish
|
|
112
|
+
too (`[governedDocument/deadWiring]`); so does a reworded question while the
|
|
113
|
+
confirmation is off.
|
|
114
|
+
- **`--requires-one-of` holds the whole decision group** — Freigeben, Warteliste and
|
|
115
|
+
Ablehnen alike, for everyone incl. the process responsible; only „Bewerbung
|
|
116
|
+
ablehnen" (reject-anytime) stays open. Running applications on the old version are
|
|
117
|
+
not affected until they are re-pinned.
|
|
118
|
+
- **Re-publishing = a new workflow version.** `offer apply --publish` after an edit cuts
|
|
119
|
+
a new `workflow_def_versions` row (and re-pins the smartform versions).
|
|
120
|
+
|
|
121
|
+
## Related
|
|
122
|
+
- [Add a workflow node](./add-workflow-node.md) — splice a new node (incl. the
|
|
123
|
+
`contractCreate`/`contractSign` mockup pair).
|
|
124
|
+
- [Attach a form to a workflow](./attach-form-to-workflow.md) — bind a form at add time.
|
|
125
|
+
- [Name what a node reads](./addresses.md) — the address flags and `node reads`.
|
|
126
|
+
- Command reference: `plexus-cli offer workflow --help`.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Push accepted applications to Engage („Engage-Übertragung", TEMPORARY)
|
|
2
|
+
|
|
3
|
+
**When to use:** a school that still runs Engage SMIS wants each accepted
|
|
4
|
+
application transferred once, one-way, into Engage as a prospective pupil with its
|
|
5
|
+
contacts. The node `engagePush` sits right before the „angenommen" end, records
|
|
6
|
+
the push and goes on at once — the engine never waits for Engage. A stopped push opens
|
|
7
|
+
the team task „Engage-Übertragung prüfen". Each push is a document of the application,
|
|
8
|
+
„Übertragungsprotokoll" (Artefakte rail): every step, every request with what was
|
|
9
|
+
sent and what came back, and what was not sent — the acts sit in its action bar.
|
|
10
|
+
The node type is temporary and is removed with its slice.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
- A bundle on disk, a live tenant's only in a private scratch dir
|
|
14
|
+
([Edit a live tenant's offer](./edit-live-tenant-offer.md)).
|
|
15
|
+
- The mapping as a JSON file (`node.engage`; `plexus-cli offer workflow node set-engage --help`).
|
|
16
|
+
It carries the school's Engage ids — lookup ids, AIF field ids, the admission stage,
|
|
17
|
+
the address format — so it lives next to the bundle, **never in version control**.
|
|
18
|
+
The `test` tenant carries no Engage push, so there is no example offer to export;
|
|
19
|
+
`offer validate` names every gap in a mapping you write.
|
|
20
|
+
The application's stage, school year, unit, offer or applicant come from an environment
|
|
21
|
+
variable by its address: `{ "from": { "address": { "scope": "env", "key": "stage.key" } }, "lookup": "yearGroup" }`
|
|
22
|
+
(the keys: IDE tab „Umgebungsvariablen"). An older mapping with
|
|
23
|
+
`{ "from": { "context": "stageKey" } }` is refused — export again.
|
|
24
|
+
Two answers that make ONE Engage value are joined: `{ "from": { "join": [".vorname", ".nachname"] } }`
|
|
25
|
+
(space-separated, in this order, empty unless every part is answered — never half a name;
|
|
26
|
+
a lookup then keys on the joined text, e.g. `"monatlich sepa"`). An answer the form leaves
|
|
27
|
+
optional but Engage requires gets an explicit Engage value: `{ "from": { "field": ".geschlecht" },
|
|
28
|
+
"lookup": "gender", "whenEmpty": "U" }` — sent as it stands, only for a form source and only
|
|
29
|
+
when the whole answer is missing (not when a `pick` finds nothing); it fills a record that
|
|
30
|
+
goes out, it never makes an unanswered optional record (address, e-mail, nationality …) go
|
|
31
|
+
out. Never use it to turn an unanswered (possibly hidden) yes/no question into „no".
|
|
32
|
+
The mapping is Engage vocabulary: a body field like `jobTitle` is fine (publish's i18n gate
|
|
33
|
+
skips `node.engage`).
|
|
34
|
+
- A team (permission-group key) that checks a stopped transfer.
|
|
35
|
+
- The deployment's Engage push mode — deployment configuration a platform operator sets,
|
|
36
|
+
not a CLI verb. Local and staging run `dry`; prod runs `live`, but with production not
|
|
37
|
+
allowed, so only the Sandbox school is written. Every push starts as a dry run; live is the cockpit's „Jetzt live übertragen"
|
|
38
|
+
after a clean dry run. The target `production` of the Engage connection is refused
|
|
39
|
+
unless the platform operator explicitly allowed production on that deployment — also
|
|
40
|
+
in a dry run.
|
|
41
|
+
|
|
42
|
+
## Steps
|
|
43
|
+
```bash
|
|
44
|
+
# 1. The accepting edge into the end:
|
|
45
|
+
plexus-cli offer workflow node list --dir <dir>
|
|
46
|
+
|
|
47
|
+
# 2. Splice the push onto it. It names what it reads by address (single
|
|
48
|
+
# quotes!): the form instance always; the contract and the payment when the
|
|
49
|
+
# mapping reads `{ contract: … }` / `{ payment: … }` sources. An uploaded
|
|
50
|
+
# contract is `$node.<contract>.document`, a generated one (`production:
|
|
51
|
+
# resolver`) `$node.<contract>.contract`.
|
|
52
|
+
plexus-cli offer workflow node add --dir <dir> --type engagePush \
|
|
53
|
+
--id engagePush --label "Engage-Übertragung" --label-en "Engage transfer" \
|
|
54
|
+
--on-edge contract:signed \
|
|
55
|
+
--assign-team bewerbungsteam \
|
|
56
|
+
--engage-target sandbox \
|
|
57
|
+
--engage-config <scratch>/engage-mapping.json \
|
|
58
|
+
--form '$node.form.admission' --contract '$node.contract.document' \
|
|
59
|
+
--payment '$node.collectPayment.payment'
|
|
60
|
+
|
|
61
|
+
# Change them later: node set --id engagePush --form|--contract|--payment '<address>'.
|
|
62
|
+
# An old bundle that still carries `wires` is refused
|
|
63
|
+
# ([graph/retiredField]) — export it again.
|
|
64
|
+
|
|
65
|
+
# Contract fields F01–F25 (meaning not confirmed by the school): --engage-contract-fields on
|
|
66
|
+
|
|
67
|
+
# 3. Later changes to the mapping:
|
|
68
|
+
plexus-cli offer workflow node set-engage --dir <dir> --node engagePush --config <scratch>/engage-mapping.json
|
|
69
|
+
|
|
70
|
+
# 4. Validate, plan, publish (publish only with the go of the process owner).
|
|
71
|
+
plexus-cli offer validate --dir <dir>
|
|
72
|
+
plexus-cli --env <env> offer plan --dir <dir>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Verify
|
|
76
|
+
- `offer validate` shows no `[engagePush/*]` or `[address/*]` error (`[address/missing]`: no
|
|
77
|
+
`form`); `[engagePush/unmappedField]` (warning) lists mapped fields the form its `form`
|
|
78
|
+
address names does not have.
|
|
79
|
+
- `offer workflow node reads --dir <dir> --node engagePush` lists the three addresses.
|
|
80
|
+
- Every path into an `approved` end runs through the node (`[engagePush/bypassed]`).
|
|
81
|
+
- After an application reaches the node: its cockpit lists the document
|
|
82
|
+
„Übertragungsprotokoll · Engage · Sandbox · Probelauf" with the recorded requests; nothing
|
|
83
|
+
was sent. A finished dry run can run again („Probelauf wiederholen", e.g. after a form
|
|
84
|
+
correction) — a finished LIVE push never.
|
|
85
|
+
|
|
86
|
+
## Go-live (platform operator only — production school, credentials)
|
|
87
|
+
Order matters; each step names why.
|
|
88
|
+
1. **Put every offer on target `production` BEFORE the first real application starts.**
|
|
89
|
+
The target belongs to the PINNED version: an application started on a `sandbox` version
|
|
90
|
+
transfers to the Sandbox school forever, also after the offer is switched.
|
|
91
|
+
`node set` has no `--engage-target` flag: on an existing node, set its
|
|
92
|
+
`inputs.target` literal to `production` in the exported bundle, then `offer validate`
|
|
93
|
+
and `offer apply --publish`.
|
|
94
|
+
2. **Allowing production and the Engage account** are deployment configuration: they need a
|
|
95
|
+
platform operator (an agent never sets them).
|
|
96
|
+
3. **Sweep the dry runs that finished while the deployment was dry** — this needs a platform
|
|
97
|
+
operator too. A run opens its task only when it finishes, so a clean dry run from before
|
|
98
|
+
the switch would stay „Fertig" and never be transferred; the sweep (idempotent) opens
|
|
99
|
+
those tasks and reports `sandboxPinned`: the clean dry runs whose PINNED version still
|
|
100
|
+
targets the Sandbox school. They get no task (a live push would land in the Sandbox and
|
|
101
|
+
read as done) — re-pin each onto a `production` version (identical topology) or transfer
|
|
102
|
+
it by hand. The same rule refuses „Jetzt live übertragen" on such a run and opens no task
|
|
103
|
+
for it as soon as production is allowed (without that, a Sandbox live test stays
|
|
104
|
+
possible). Applications that ended without a place (rejected, withdrawn, waitlisted,
|
|
105
|
+
expired) are left out, live refuses them, and their open Engage task closes with them.
|
|
106
|
+
Every opened task „Engage-Übertragung prüfen" ends with „Jetzt live übertragen" (or with a
|
|
107
|
+
fixed answer + „Probelauf wiederholen" when the dry run lists issues). Test applications
|
|
108
|
+
are left out — they never go live.
|
|
109
|
+
|
|
110
|
+
## Gotchas
|
|
111
|
+
- **Engage has no idempotency key.** Never re-run a push by hand: „Erneut übertragen"
|
|
112
|
+
resumes at the first open step and first asks Engage whether an unclear create landed.
|
|
113
|
+
An id the team types in is read back by id before it is taken.
|
|
114
|
+
- A create answers with the new id (`{"newPupilID":"4068"}`, `newContactID`, `newAddressID` —
|
|
115
|
+
observed in the sandbox write test); it is read back by id before it is taken. Without one, the id
|
|
116
|
+
comes from the difference of the list, verified the same way — never from a name search.
|
|
117
|
+
- A write without a body (`LinkAddressToPupil`) is sent with an EMPTY body: Engage answers
|
|
118
|
+
`411 Length Required` to a body-less PUT.
|
|
119
|
+
- A sibling already at the school holds the contact steps for the team: link the
|
|
120
|
+
existing Engage contact id or create a new contact.
|
|
121
|
+
- The API cannot enrol: the pupil lands as a prospective pupil at the configured
|
|
122
|
+
admission stage. Whether Engage enrols from its completion stage is open.
|
|
123
|
+
- A fee billed separately (`settlement: separate`) is never sent as „paid".
|
|
124
|
+
- **A dry run that waits for the team opens its task „Engage-Übertragung prüfen"**: when
|
|
125
|
+
it lists an issue (fix the answer or the mapping, then „Probelauf wiederholen"), or on a live
|
|
126
|
+
deployment when nothing stands between it and „Jetzt live übertragen". A clean re-run on a dry
|
|
127
|
+
deployment or „Jetzt live übertragen" closes it; a stop of the live run opens the live row's
|
|
128
|
+
own task. A gap that lies in the PINNED mapping (a value without an Engage id) keeps the task
|
|
129
|
+
open until the application is re-pinned or the answer changes.
|
|
130
|
+
- **The mapping an application uses is the one of its PINNED version.** A mapping fix reaches
|
|
131
|
+
applications started after the publish; older ones keep theirs (re-pin only with an identical
|
|
132
|
+
topology).
|
|
133
|
+
- **Address lines for address format `CL1-117`:** line 1 street + number (`subdwelling`), line 3
|
|
134
|
+
town (`street`), line 6 postcode (`postcode`). Line 5 feeds `town` — a postcode there is lost.
|
|
135
|
+
- **A lookup table is keyed by the exact value its source delivers — check each source's
|
|
136
|
+
vocabulary, `offer validate` does not.** The address field's `land` is its own closed
|
|
137
|
+
vocabulary in upper case (`DE`/`AT`/`CH`/`OTHER`), not the
|
|
138
|
+
lower-case ISO keys of a `countries` list. One `country` table for both made every
|
|
139
|
+
address „unmapped" (`[engagePush/unmappedLookup] … „DE"`), seen first in a production
|
|
140
|
+
dry run. Give such a source its own table (`addressCountry`). Leave a value
|
|
141
|
+
like `OTHER` unmapped: it names no country, and the push reports it instead of guessing.
|
|
142
|
+
Before going live, a dry run of an application with realistic data must list no issue
|
|
143
|
+
(„Jetzt live übertragen" is hidden while any issue is listed).
|
|
144
|
+
|
|
145
|
+
## Related
|
|
146
|
+
- [Name what a node reads](./addresses.md) · [Edit a live tenant's offer](./edit-live-tenant-offer.md)
|
|
147
|
+
- `plexus-cli offer workflow node add --help` (`--engage-*` flags) · `plexus-cli offer workflow node set-engage --help`
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Insert a node on one edge and rewire it
|
|
2
|
+
|
|
3
|
+
**When to use:** a new step must sit between two existing ones — e.g. „Unterlagen prüfen"
|
|
4
|
+
between the form and the first decision — and it must land on an existing board column
|
|
5
|
+
instead of adding one. Replaces the hand-written bundle edits of `apply-doccheck.py`
|
|
6
|
+
(insert a `review` node, re-point `form.next.standard`, add a progress mapping).
|
|
7
|
+
|
|
8
|
+
## Prerequisites
|
|
9
|
+
- An offer bundle on disk (`offer export --slug <slug> --out <dir>`). Fully offline: every
|
|
10
|
+
command runs the publish gate on the result and writes nothing when it fails.
|
|
11
|
+
- The ids of the edge you cut: `plexus-cli offer workflow node list --dir <dir>` shows each
|
|
12
|
+
node's outcomes and targets.
|
|
13
|
+
- The state ids of the process board: `plexus-cli offer workflow show --dir <dir>`.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
```bash
|
|
17
|
+
# A review step on exactly the edge form —standard→ (whatever it pointed at):
|
|
18
|
+
plexus-cli offer workflow node add --dir <dir> --type review --id docCheck \
|
|
19
|
+
--label "Unterlagen prüfen" --label-en "Check documents" \
|
|
20
|
+
--reads '$node.form.admission.kind.masernschutz,$node.form.admission.kind.proofOfIdentity' \
|
|
21
|
+
--on-edge form:standard \
|
|
22
|
+
--progress reviewing=eingereicht \
|
|
23
|
+
--assign-decision bewerbungsteam
|
|
24
|
+
|
|
25
|
+
# Any other type works the same way, e.g. a waiting list on ONE decision outcome:
|
|
26
|
+
plexus-cli offer workflow node add --dir <dir> --type waitlist --id warteliste \
|
|
27
|
+
--label "Warteliste" --label-en "Waiting list" --on-edge decision:waitlisted
|
|
28
|
+
|
|
29
|
+
# Re-route an existing node's outcome afterwards:
|
|
30
|
+
plexus-cli offer workflow node set --dir <dir> --id docCheck --outcomes reviewed:decision
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- `--on-edge <from>:<outcome>` re-points exactly that edge to the new node; the new node's
|
|
34
|
+
outcomes continue to the edge's old target (route others with `--outcomes`). A sibling
|
|
35
|
+
outcome of `<from>` that reaches the same target keeps its route — unlike `--after`, which
|
|
36
|
+
rewires every edge of the anchor that points at its first target. The two exclude each other.
|
|
37
|
+
- `--progress <event>=<stateId>` puts the node's progress event on a state the board already
|
|
38
|
+
has (the family keeps reading „Eingereicht"). Without it the node gets its own state and
|
|
39
|
+
column — for a review that is a second „In Prüfung" column, which the board's
|
|
40
|
+
distinct-label rule (`checkProgressBoardDistinctLabels`) refuses.
|
|
41
|
+
- `--reads` names the fields a reviewer of a `--type review` ticks (entered, non-repeated
|
|
42
|
+
fields only), each by its full address `$node.<formNode>.admission.<field>` (single
|
|
43
|
+
quotes; a bare key is refused with the addresses visible at the new node). Without it the
|
|
44
|
+
review ticks nothing and still parks. Other node types declare reads with
|
|
45
|
+
`node set-reads` (which also takes the short form `--from <formNode> --field <path>,…`).
|
|
46
|
+
The form must run on every path before the new node (`[address/notVisible]` otherwise).
|
|
47
|
+
|
|
48
|
+
## Verify
|
|
49
|
+
```bash
|
|
50
|
+
plexus-cli offer validate --dir <dir>
|
|
51
|
+
plexus-cli offer workflow node list --dir <dir>
|
|
52
|
+
plexus-cli --env staging --tenant <t> offer plan --dir <dir> # expect: ~ workflow (+ ~ smartform if fields changed)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Idempotency / gotchas
|
|
56
|
+
- Not idempotent: a second `node add` with the same `--id` is refused (`already exists`).
|
|
57
|
+
- An event the node type does not emit, or a state the board does not have, is refused by
|
|
58
|
+
name (`emits no progress event …`, `no state … on the process board`).
|
|
59
|
+
- A review holds every non-rejecting outcome until all `reads` fields are ticked — so a
|
|
60
|
+
waiting-list exit belongs on the decision after it, not on the review.
|
|
61
|
+
- Making the read fields required is a form edit: `offer form field set --key <k> --required`.
|
|
62
|
+
- Nothing here touches a live process until `offer apply --publish`; running applications
|
|
63
|
+
stay on their pinned version.
|
|
64
|
+
|
|
65
|
+
## Related
|
|
66
|
+
- [Add a workflow node](./add-workflow-node.md) · [Edit a workflow node](./edit-workflow-node.md)
|
|
67
|
+
- [Name what a node reads](./addresses.md) · [Declare what a document node reads](./declare-node-reads.md) · [Edit a live tenant's offer](./edit-live-tenant-offer.md)
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Author a workflow node's tasks
|
|
2
|
+
|
|
3
|
+
**When to use:** give a workflow node a task a team must do — with a typed result
|
|
4
|
+
(„Empfehlung", „Auswahl", Freitext, a priced item or a reduction), a blocking edge onto the same or a later node, a
|
|
5
|
+
spawn condition, evidence fields or its plain-text description — or change / remove one, without
|
|
6
|
+
hand-editing `workflow.json`. Works on any bundle: the `test` template, a fixture, or a
|
|
7
|
+
live tenant's export (then follow [Edit a live tenant's offer](./edit-live-tenant-offer.md)
|
|
8
|
+
around it).
|
|
9
|
+
|
|
10
|
+
## The model in four lines
|
|
11
|
+
- A task (`node.tasks[]`, key unique per node) spawns when its node is entered — with
|
|
12
|
+
`--when`, only while that **boolean form export** holds. Everything a task reads names
|
|
13
|
+
its producer by full address (single quotes): `--when` / `--reads`
|
|
14
|
+
(`'$node.<formNode>.admission.<field>'`, one form per task — `[address/mixedForms]`),
|
|
15
|
+
`--documents` (`artifact:<own slot>`, `field:<address>`, `document:$node.<node>.document`),
|
|
16
|
+
`--family-request-fields <addresses>` / `--family-request-from '$node.<formNode>.admission'`,
|
|
17
|
+
a record field's `"suggest":{"kind":"form","address":"$node.…"}`. A bare key is refused
|
|
18
|
+
with the addresses visible at the node; the producer must run on every path before it
|
|
19
|
+
(`[address/notVisible]`). A value a task records is `$task.<taskKey>.<storeKey>` for its
|
|
20
|
+
readers — renaming the task key changes that address.
|
|
21
|
+
- `--blocks <templateKey>` withholds a sibling's actions on the same node;
|
|
22
|
+
`--blocks <nodeId>:<templateKey>` withholds a template on a **later** node (a
|
|
23
|
+
cross-node blocker: it survives its node and needs a `--result`). Intrinsic targets:
|
|
24
|
+
`decision`, `prepareDocument`, `releaseApproval`. The target's **whole** action group
|
|
25
|
+
waits — on a decision Freigeben, Warteliste, Ablehnen, and Nachrücken on the waitlist
|
|
26
|
+
it routes into. There is no partial hold; the staff escape is „Bewerbung
|
|
27
|
+
ablehnen".
|
|
28
|
+
- A task with `--result` closes only by recording it; `--chat` posts a result with text
|
|
29
|
+
into `all`, `team:<group>` or an authored channel key — never `external`.
|
|
30
|
+
- A result **with a value** (`choice`, `pricedItem`, `reduction`) writes it under the
|
|
31
|
+
task's own address — `--writes '$task.<thisTaskKey>.<storeKey>'`, stored as the bare
|
|
32
|
+
`result.writes` — and names it with `--result-label` (`--result-label-en`). A
|
|
33
|
+
`pricedItem` names its article with `--item <catalog key>` (not an address: the key of
|
|
34
|
+
the billing item); a `reduction` the derived price it lowers with
|
|
35
|
+
`--prices '$derived.<key>'`.
|
|
36
|
+
- The CLI checks **shape**; the graph rules (`[workItems/*]`, `[taskResult/*]`) are the
|
|
37
|
+
publish validators, run before every write and by `offer validate`.
|
|
38
|
+
|
|
39
|
+
## Steps
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
B=<bundle dir>
|
|
43
|
+
|
|
44
|
+
# What a node carries today.
|
|
45
|
+
plexus-cli offer workflow node list --dir $B
|
|
46
|
+
jq '.graph.nodes[] | {id, tasks}' $B/workflow.json # the tasks themselves
|
|
47
|
+
|
|
48
|
+
# 1. A cross-node blocker with a recommendation, posted to the whole team chat:
|
|
49
|
+
# the review team's estimate holds the whole Aufnahme decision.
|
|
50
|
+
plexus-cli offer workflow node task add --dir $B --node reviewEingereicht --key einschaetzung \
|
|
51
|
+
--title "Einschätzung abgeben" --title-en "Give an assessment" \
|
|
52
|
+
--team oeffentlichkeitsarbeit --due-in-days 3 \
|
|
53
|
+
--blocks aufnahme:decision \
|
|
54
|
+
--result recommendation --chat all
|
|
55
|
+
|
|
56
|
+
# 2. A conditional choice task that holds the contract (the reduced-fee shape):
|
|
57
|
+
# it exists only while the family asked for a reduction, comes back when the
|
|
58
|
+
# answer returns to „Ja", and is judged again when the income proofs change.
|
|
59
|
+
plexus-cli offer workflow node task add --dir $B --node contract --key ermaessigung \
|
|
60
|
+
--title "Ermäßigung prüfen" --team finanzen --due-in-days 5 \
|
|
61
|
+
--blocks prepareDocument \
|
|
62
|
+
--result choice --option voll="Voller Beitrag|Full fee" --option halb="Halbiert|Halved" \
|
|
63
|
+
--text-required --chat team:finanzen \
|
|
64
|
+
--when '$node.form.admission.ermaessigungBeantragt' --on-condition-return respawn \
|
|
65
|
+
--reads '$node.form.admission.gebuehren.einkommensnachweise' \
|
|
66
|
+
--description "Nachweise prüfen und die Ermäßigung berechnen." \
|
|
67
|
+
--description-en "Check the proofs and calculate the reduction."
|
|
68
|
+
|
|
69
|
+
# 3. A reduction that lowers the derived tuition (the `test` template's shape): it
|
|
70
|
+
# writes its deduction under its own address and names the price it lowers.
|
|
71
|
+
# The derived price must be declared in graph.processStore with
|
|
72
|
+
# derive.reduction = $task.reducedFee.reducedFee ([process/reductionPrices]).
|
|
73
|
+
plexus-cli offer workflow node task add --dir $B --node reviewEingereicht --key reducedFee \
|
|
74
|
+
--title "Ermäßigung berechnen" --team finanzen \
|
|
75
|
+
--result reduction --writes '$task.reducedFee.reducedFee' --prices '$derived.schulgeld' \
|
|
76
|
+
--result-label "Einkommensermäßigung (Abzug)" --result-label-en "Income-based reduction (deduction)" \
|
|
77
|
+
--chat team:finanzen
|
|
78
|
+
# A priced item names its article instead:
|
|
79
|
+
# --result pricedItem --item tuition --writes '$task.<key>.<storeKey>' --result-label "Schulgeld"
|
|
80
|
+
|
|
81
|
+
# 4. Change only what you name (everything else stays).
|
|
82
|
+
plexus-cli offer workflow node task set --dir $B --node reviewEingereicht --key einschaetzung --text-required
|
|
83
|
+
plexus-cli offer workflow node task set --dir $B --node contract --key ermaessigung --clear-description
|
|
84
|
+
|
|
85
|
+
# 5. Remove a task (refused while another task's --blocks still names it — the
|
|
86
|
+
# refusal lists the dependents; retarget or --clear-blocks them first).
|
|
87
|
+
plexus-cli offer workflow node task rm --dir $B --node contract --key ermaessigung
|
|
88
|
+
|
|
89
|
+
# 6. Gate, diff, release.
|
|
90
|
+
plexus-cli offer validate --dir $B
|
|
91
|
+
plexus-cli --env <env> offer plan --tenant <t> --dir $B
|
|
92
|
+
plexus-cli --env <env> offer apply --tenant <t> --dir $B --publish
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Every verb prints a field diff (`before` / `after`); `--json` gives
|
|
96
|
+
`{action, node, key, before, after, changes, dropped}`.
|
|
97
|
+
|
|
98
|
+
## Example: move a task to another node on a live tenant
|
|
99
|
+
|
|
100
|
+
A form task `oeaEinschaetzung` on `formAnmeldung` should become one recommendation task
|
|
101
|
+
on the review node that holds the Aufnahme decision (reject / waitlist stay open).
|
|
102
|
+
Work in a scratch dir and keep an untouched copy to diff against:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
WORK=<scratch dir>/$(date +%F)-einschaetzung
|
|
106
|
+
T=<slug>; S=<offer-slug>
|
|
107
|
+
plexus-cli --env prod offer export --tenant $T --slug $S --out $WORK/$S
|
|
108
|
+
cp -a $WORK/$S $WORK/$S.orig
|
|
109
|
+
|
|
110
|
+
plexus-cli offer workflow node task rm --dir $WORK/$S --node formAnmeldung --key oeaEinschaetzung
|
|
111
|
+
plexus-cli offer workflow node task add --dir $WORK/$S --node reviewEingereicht --key einschaetzung \
|
|
112
|
+
--title "Einschätzung abgeben" --team oeffentlichkeitsarbeit --due-in-days 3 \
|
|
113
|
+
--blocks aufnahme:decision \
|
|
114
|
+
--result recommendation --chat all
|
|
115
|
+
|
|
116
|
+
diff -ru $WORK/$S.orig $WORK/$S # exactly these two tasks
|
|
117
|
+
plexus-cli offer validate --dir $WORK/$S
|
|
118
|
+
plexus-cli --env prod offer plan --tenant $T --dir $WORK/$S
|
|
119
|
+
plexus-cli --env prod offer apply --allow-prod --tenant $T --dir $WORK/$S --publish
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
If `offer plan` refuses task fields that `offer validate` accepts, the deployment runs an
|
|
123
|
+
older release than your CLI — that needs a platform operator, not a bundle edit.
|
|
124
|
+
|
|
125
|
+
## Verify
|
|
126
|
+
- `offer validate --dir $B` → clean.
|
|
127
|
+
- After publish, a new application reaching the node shows the task in the cockpit's
|
|
128
|
+
task rail („Empfehlung erfassen"), and the blocked target's actions stay held until
|
|
129
|
+
the result is recorded.
|
|
130
|
+
|
|
131
|
+
## Gotchas
|
|
132
|
+
- **Only errors the edit introduces block the write.** Errors the bundle already carried
|
|
133
|
+
print as `⚠ vorbestehend …` and do not stop you — but `offer apply --publish` still
|
|
134
|
+
refuses them.
|
|
135
|
+
- **`--title` without `--title-en` writes the German into both locales**; `--title-en`
|
|
136
|
+
alone relabels English only.
|
|
137
|
+
- **`blocks.except` is retired** — `offer validate` refuses a bundle that still
|
|
138
|
+
carries it (`[workItems/blocksExceptRetired]`); re-setting `--blocks` drops it
|
|
139
|
+
(`⚠ blocks.except entfällt`). A result kind change drops
|
|
140
|
+
options / `textRequired` / `writes` / `label` / `item` / `prices` that no longer fit
|
|
141
|
+
(each listed under `dropped`), and keeps `chat`.
|
|
142
|
+
- **`--writes` takes this task's own address only** — `'$task.<key>.<storeKey>'` without a
|
|
143
|
+
path; a bare key, another task's address or a path is refused. `--prices` takes
|
|
144
|
+
`'$derived.<key>'`. Whether the store key is declared and the reduction's
|
|
145
|
+
`derive.reduction` points back at this task is the publish gate's check
|
|
146
|
+
(`[process/*]`).
|
|
147
|
+
- **`--option` replaces the whole list** — repeat every entry you keep.
|
|
148
|
+
- **`--description` is plain text under the title, never a checklist.** There are no
|
|
149
|
+
checklist steps any more (a bundle still carrying `steps` is refused at publish,
|
|
150
|
+
`[workItems/unknownKey]`, like any key a task does not declare); several work steps are several tasks (a `spawnTasks`
|
|
151
|
+
optional action, chained by `blocks`). Without `--description-en` the German stands in
|
|
152
|
+
for English.
|
|
153
|
+
- **An old bundle** (bare keys in `when` / `reads` / documents /
|
|
154
|
+
`familyRequest` / `suggest`) is refused (`[address/bareIdentifier]`) — export it again.
|
|
155
|
+
- **Offline, team and channel existence are not checked** — the tenant's permission
|
|
156
|
+
groups are known only at `offer apply --publish`.
|
|
157
|
+
- **The positional `node add|set --task`** replaces a node's whole task list and knows
|
|
158
|
+
none of the fields above; use it only to scaffold a new node.
|
|
159
|
+
|
|
160
|
+
## Related
|
|
161
|
+
- [Name what a node reads](./addresses.md) · [Edit a workflow node](./edit-workflow-node.md) · [Author default chat channels](./workflow-default-channels.md)
|
|
162
|
+
- `plexus-cli offer workflow node task add --help` (every result kind and flag)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Ask for an optional assessment („Einschätzung einholen")
|
|
2
|
+
|
|
3
|
+
**Use it to** model assessments the decision does not have to wait for: the
|
|
4
|
+
Öffentlichkeitsarbeit may say „Keine Einschätzung abgeben", the Schulleitung attaches a
|
|
5
|
+
Beurteilung as a file, and the Sekretariat can ask the Geschäftsführung for one more
|
|
6
|
+
assessment from the „Weiteres" menu — without a letter to the family.
|
|
7
|
+
|
|
8
|
+
## The model
|
|
9
|
+
|
|
10
|
+
- **Optional task** (`optional: { skipLabel: { de, en } }`): nothing waits for it. The
|
|
11
|
+
task holds no step, so publish refuses it together with `blocks`, `gatesNode`,
|
|
12
|
+
`locksEvidence` and `completableIf` (`[workItems/optionalHolds]`). Its holder closes it
|
|
13
|
+
with its result or with the skip button. The Sekretariat skips it by deciding: an open
|
|
14
|
+
optional task then reads „Aufgabe hinfällig" in the Verlauf, naming the decider.
|
|
15
|
+
The result must be prose: free text, a recommendation, or a choice without `writes`
|
|
16
|
+
(`[workItems/optionalNeedsProseResult]`). A task of an action listed in `requiresOneOf`
|
|
17
|
+
is never optional (`[workItems/optionalInRequiresOneOf]`).
|
|
18
|
+
- **Files** (`result.files: true`): the person attaches up to 20 files next to the text.
|
|
19
|
+
Text and files go into the result's chat as one message. Find them later in the cockpit
|
|
20
|
+
under Verlauf/Aktivitäten (tab of the chat the result names), shown only to people who
|
|
21
|
+
read that chat — never under „Dokumente"
|
|
22
|
+
([task-result-files.md](./task-result-files.md)).
|
|
23
|
+
- **„Einschätzung einholen"** is a `spawnTasks` optional action that references an optional
|
|
24
|
+
task assigned to a role (`--team geschaeftsfuehrung`). Pressing the action spawns that
|
|
25
|
+
task. A triggered optional task does not hold the decision. An internal task never
|
|
26
|
+
writes to the family.
|
|
27
|
+
|
|
28
|
+
## CLI
|
|
29
|
+
|
|
30
|
+
Use a scratch dir for a real tenant
|
|
31
|
+
([edit-live-tenant-offer.md](./edit-live-tenant-offer.md)).
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# 1. The ÖA assessment: optional, no longer blocking the decision
|
|
35
|
+
plexus-cli offer workflow node task set --dir <dir> --node aufnahme --key oeaEinschaetzung \
|
|
36
|
+
--clear-blocks --optional "Keine Einschätzung abgeben" --optional-en "No assessment"
|
|
37
|
+
|
|
38
|
+
# 2. The Schulleitung's assessment takes files (it may stay owed — keep its blocks)
|
|
39
|
+
plexus-cli offer workflow node task set --dir <dir> --node aufnahme --key schulleitungPruefung --files
|
|
40
|
+
|
|
41
|
+
# 3. The task the action spawns, then the action
|
|
42
|
+
plexus-cli offer workflow node task add --dir <dir> --node aufnahme --key gfEinschaetzung \
|
|
43
|
+
--title "Einschätzung Geschäftsführung" --title-en "Management assessment" \
|
|
44
|
+
--team geschaeftsfuehrung --due-in-days 3 --result freetext --chat all --files \
|
|
45
|
+
--optional "Keine Einschätzung abgeben" --optional-en "No assessment"
|
|
46
|
+
plexus-cli offer workflow node optional-action set --dir <dir> --node aufnahme --key einschaetzung \
|
|
47
|
+
--label "Einschätzung einholen" --label-en "Request an assessment" \
|
|
48
|
+
--tasks gfEinschaetzung --trigger bewerbungsteam --repeatable
|
|
49
|
+
|
|
50
|
+
plexus-cli offer validate --dir <dir>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The group named by `--team` must hold `aufgaben.*` rights, or its members cannot open the
|
|
54
|
+
task (`tenant_admin` usually holds none). A rights failure blocks nothing at publish; it
|
|
55
|
+
only shows up in the cockpit.
|
|
56
|
+
|
|
57
|
+
## Verify
|
|
58
|
+
|
|
59
|
+
1. Cockpit, application on `aufnahme`: the decision row shows „Wartet auf: …" for
|
|
60
|
+
every task that still blocks it, but not for optional ones.
|
|
61
|
+
2. As the ÖA member, open the task. The dialog shows „Keine Einschätzung abgeben" next to
|
|
62
|
+
„Ergebnis erfassen". After a skip, the Verlauf card reads „Keine Einschätzung abgeben".
|
|
63
|
+
3. As the Sekretariat, use „Weiteres → Einschätzung einholen". The Geschäftsführung's queue
|
|
64
|
+
gets the task, and the family's Verlauf gets nothing.
|
|
65
|
+
4. Testmodus: „<Aufgabe> (Test): Keine Einschätzung abgeben" skips through the real verb.
|