@things-factory/worklist 10.1.208 → 10.1.209
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/dist-client/components/timeline-entries.js +2 -1
- package/dist-client/components/timeline-entries.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-view.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.js +36 -12
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +1 -2
- package/dist-client/pages/todo/draft-list-page.js +11 -14
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/check-authority.d.ts +2 -13
- package/dist-server/controllers/activity-approval/check-authority.js +2 -49
- package/dist-server/controllers/activity-approval/check-authority.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegate.js +1 -8
- package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegation.d.ts +5 -15
- package/dist-server/controllers/activity-approval/delegation.js +2 -16
- package/dist-server/controllers/activity-approval/delegation.js.map +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.d.ts +2 -2
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js.map +1 -1
- package/dist-server/controllers/activity-approval/seat-standing.d.ts +66 -0
- package/dist-server/controllers/activity-approval/seat-standing.js +57 -0
- package/dist-server/controllers/activity-approval/seat-standing.js.map +1 -0
- package/dist-server/controllers/activity-instance/issue.js +9 -15
- package/dist-server/controllers/activity-instance/issue.js.map +1 -1
- package/dist-server/controllers/activity-thread/abort.js +7 -0
- package/dist-server/controllers/activity-thread/abort.js.map +1 -1
- package/dist-server/controllers/activity-thread/restart.js +4 -2
- package/dist-server/controllers/activity-thread/restart.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js +5 -1
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/controllers/common.js +1 -1
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/service/activity/index.d.ts +2 -2
- package/dist-server/service/activity-approval/index.d.ts +1 -1
- package/dist-server/service/activity-approval/my-pending-approvals.d.ts +5 -5
- package/dist-server/service/activity-approval/my-pending-approvals.js +5 -8
- package/dist-server/service/activity-approval/my-pending-approvals.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.d.ts +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +9 -4
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/index.d.ts +1 -1
- package/dist-server/service/activity-instance/request-box.d.ts +2 -0
- package/dist-server/service/activity-instance/request-box.js +18 -0
- package/dist-server/service/activity-instance/request-box.js.map +1 -0
- package/dist-server/service/activity-summary/activity-summary-query.js +3 -3
- package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
- package/dist-server/service/activity-summary/index.d.ts +1 -1
- package/dist-server/service/activity-template/index.d.ts +2 -2
- package/dist-server/service/activity-thread/index.d.ts +1 -1
- package/dist-server/service/activity-thread/my-open-threads.d.ts +1 -2
- package/dist-server/service/activity-thread/my-open-threads.js +2 -3
- package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
- package/dist-server/service/index.d.ts +3 -3
- package/dist-server/service/subscription/subscription-filters.d.ts +2 -2
- package/dist-server/service/subscription/subscription-filters.js +2 -2
- package/dist-server/service/subscription/subscription-filters.js.map +1 -1
- package/dist-server/service/work-door/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/shared/task-followup.d.ts +9 -0
- package/shared/task-followup.js +25 -0
- package/tests/delegate-approval.test.ts +7 -4
- package/tests/open-doors.test.ts +1 -1
- package/translations/en.json +4 -3
- package/translations/es.json +4 -3
- package/translations/ja.json +4 -3
- package/translations/ko.json +4 -3
- package/translations/ms.json +4 -3
- package/translations/zh.json +4 -3
- package/dist-server/controllers/activity-approval/own-request.d.ts +0 -162
- package/dist-server/controllers/activity-approval/own-request.js +0 -135
- package/dist-server/controllers/activity-approval/own-request.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/worklist",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.209",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"@things-factory/scheduler-client": "^10.1.208",
|
|
65
65
|
"@things-factory/shell": "^10.1.208"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "f0775da623f1d73007d41d676be9e1a8bed30325"
|
|
68
68
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A rejected request is a record, never a new approval. Source work submits a fresh case. */
|
|
2
|
+
export function followupActions(thread: any): {
|
|
3
|
+
sourceResubmission: boolean
|
|
4
|
+
restartable: boolean
|
|
5
|
+
abortable: boolean
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Application-relative page addresses only; never let a payload navigate off-site. */
|
|
9
|
+
export function sourceAddress(value: unknown): string | undefined
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* What a task's screen offers after a rejection or while a task is held — read by the thread page and its test.
|
|
3
|
+
* Hand-written .js with a .d.ts beside it, as `decision-sentences`: a .ts here would be taken into the client's
|
|
4
|
+
* compile and move its rootDir up to the package root (dist-client/client/…), breaking the package's entry point.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** A rejected request is a record, never a new approval. Source work submits a fresh case. */
|
|
8
|
+
function followupActions(thread) {
|
|
9
|
+
const instance = thread?.activityInstance
|
|
10
|
+
const closed = ['ended', 'aborted'].includes(instance?.state)
|
|
11
|
+
return {
|
|
12
|
+
sourceResubmission: thread?.round > 1 && !!(instance?.rejectionIsFinal || instance?.activity?.rejectionIsFinal),
|
|
13
|
+
restartable: !closed && thread?.state === 'rejected' && !instance?.rejectionIsFinal && !instance?.activity?.rejectionIsFinal,
|
|
14
|
+
// Only a held task: never claim an unassigned pool item just to stop it.
|
|
15
|
+
abortable: !closed && !!thread?.assignee?.id && ['assigned', 'started', 'rejected'].includes(thread?.state)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Application-relative page addresses only; never let a payload navigate off-site. */
|
|
20
|
+
function sourceAddress(value) {
|
|
21
|
+
return typeof value === 'string' && /^[a-z][a-z0-9-]*(?:\?[^\s\\#]*)?$/.test(value) ? value : undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
exports.followupActions = followupActions
|
|
25
|
+
exports.sourceAddress = sourceAddress
|
|
@@ -4,8 +4,9 @@ import { join } from 'path'
|
|
|
4
4
|
* Handing an approval seat on, through the real controller on sqlite.
|
|
5
5
|
*
|
|
6
6
|
* What the controller has to carry that the pure decision (test/delegation.test.ts) cannot: the seat
|
|
7
|
-
* keeps what it is on the new row, and the
|
|
8
|
-
*
|
|
7
|
+
* keeps what it is on the new row, and the two refusals are asked of the people actually loaded - the
|
|
8
|
+
* receiver's domains. Whoever raised the case may take a seat like anyone else (2026-10-23, ADR-0052 ②
|
|
9
|
+
* withdrawn).
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
const { createSqliteTestDataSource } = require(join(__dirname, '..', '..', 'ops-master', 'test', 'support', 'database.cjs'))
|
|
@@ -99,10 +100,12 @@ it('someone of another tenant is refused, and the seat is still the holder\'s',
|
|
|
99
100
|
expect(await db.getRepository(ActivityApproval).findOne({ where: { id: seat.id } })).toMatchObject({ judgment: '' })
|
|
100
101
|
})
|
|
101
102
|
|
|
102
|
-
it('a judging seat to whoever raised the case
|
|
103
|
+
it('a judging seat goes to whoever raised the case - the one who raises a case may judge it', async () => {
|
|
103
104
|
const seat = await aSeat('approval')
|
|
104
105
|
|
|
105
|
-
await
|
|
106
|
+
await handOn(seat, issuer)
|
|
107
|
+
|
|
108
|
+
expect(await newRowFor(seat, issuer)).toMatchObject({ judgment: '', participation: 'approval' })
|
|
106
109
|
})
|
|
107
110
|
|
|
108
111
|
it('to its own holder is refused', async () => {
|
package/tests/open-doors.test.ts
CHANGED
|
@@ -86,7 +86,7 @@ const OPEN_BY_DECISION: Record<Root, Record<string, string>> = {
|
|
|
86
86
|
endActivityThread: 'checkAuthority - only the assignee',
|
|
87
87
|
abortActivityThread: 'checkAuthority - only the assignee',
|
|
88
88
|
delegateActivityThread: 'checkAuthority - only the assignee',
|
|
89
|
-
approveActivityApproval: 'checkAuthority - only the approver
|
|
89
|
+
approveActivityApproval: 'checkAuthority - only the approver',
|
|
90
90
|
rejectActivityApproval: 'checkAuthority - only the approver',
|
|
91
91
|
saveActivityApproval: 'checkAuthority - only the approver',
|
|
92
92
|
delegateActivityApproval: 'checkAuthority - only the approver',
|
package/translations/en.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "Revise request",
|
|
3
|
+
"button.task-open-source": "Open source work",
|
|
4
|
+
"text.task-source-resubmit": "Edit the source and submit a new request. The rejected request remains in history.",
|
|
5
|
+
"text.task-abort-keeps-history": "Stop this task? Approval history is kept and the source work is not cancelled.",
|
|
2
6
|
"button.try-again": "try again",
|
|
3
7
|
"button.discard-draft": "discard draft",
|
|
4
8
|
"button.abort": "abort",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "submit",
|
|
25
29
|
"button.unschedule-task": "unschedule task",
|
|
26
30
|
"error.activity not found": "this task template ({activity}) cannot be found.",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "you raised this request, so someone else has to judge it. if nobody else stands on this approval line, ask an administrator to add an approver.",
|
|
28
31
|
"error.activity-approval is already terminated": "this approval task ({activityApproval}) has already been terminated ({actual}).",
|
|
29
32
|
"error.activity-approval is reference only": "you are a reference on this item, so you cannot approve or reject it. you can leave a comment.",
|
|
30
33
|
"error.activity-approval not found": "this approval task ({activityApproval}) cannot be found.",
|
|
31
34
|
"error.activity-approval delegate to self": "the task is already yours; choose someone else to hand it to.",
|
|
32
35
|
"error.activity-approval delegate outside domain": "that person is not in this site, so the task cannot be handed to them.",
|
|
33
|
-
"error.activity-approval delegate to issuer": "the person who raised this cannot approve it, so it cannot be handed to them.",
|
|
34
36
|
"error.activity-approval taken by someone else": "someone else handled this approval first. reload the list to see where it stands.",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id} is someone else's draft. Only the person who wrote it, or someone who manages activity instances, may edit or issue it.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} is assigned to another role. only someone with that role can pick it.",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "this task thread ({id}) is {actual}. this can only be done in {state}.",
|
|
57
59
|
"error.activity-thread should not be submitted": "this task thread ({id}) is already in {actual} status.",
|
|
58
60
|
"error.all activity threads should be terminated": "thread ({activityThread}) is still {state}. try again after all threads are terminated.",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats}: no approver other than you. add another approver to that step, or give that role to someone else.",
|
|
60
61
|
"error.approval line names a person who cannot be found": "{seats}: the person named for that step cannot be found. name another approver.",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats}: nobody holds the role named for that step. add someone to that role.",
|
|
62
63
|
"error.approval-line-missing": "this form has no approval line. set who approves it.",
|
package/translations/es.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "Revisar solicitud",
|
|
3
|
+
"button.task-open-source": "Abrir trabajo de origen",
|
|
4
|
+
"text.task-source-resubmit": "Edite el origen y envíe una nueva solicitud. La solicitud rechazada permanece en el historial.",
|
|
5
|
+
"text.task-abort-keeps-history": "¿Detener esta tarea? Se conserva el historial de aprobación y no se cancela el trabajo de origen.",
|
|
2
6
|
"button.try-again": "reintentar",
|
|
3
7
|
"button.discard-draft": "descartar borrador",
|
|
4
8
|
"button.abort": "cancelar",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "enviar",
|
|
25
29
|
"button.unschedule-task": "quitar tarea de la programación",
|
|
26
30
|
"error.activity not found": "no se encuentra esta plantilla de tarea ({activity}).",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "usted envió esta solicitud, así que otra persona debe resolverla. si nadie más figura en esta línea de aprobación, pida a un administrador que añada un aprobador.",
|
|
28
31
|
"error.activity-approval is already terminated": "esta tarea de aprobación ({activityApproval}) ya ha finalizado ({actual}).",
|
|
29
32
|
"error.activity-approval is reference only": "usted figura como referencia en este elemento, así que no puede aprobarlo ni rechazarlo. puede dejar un comentario.",
|
|
30
33
|
"error.activity-approval not found": "no se encuentra esta tarea de aprobación ({activityApproval}).",
|
|
31
34
|
"error.activity-approval delegate to self": "la tarea ya es suya; elija a otra persona a quien delegarla.",
|
|
32
35
|
"error.activity-approval delegate outside domain": "esa persona no pertenece a este sitio, así que no se le puede delegar la tarea.",
|
|
33
|
-
"error.activity-approval delegate to issuer": "la persona que envió esto no puede aprobarlo, así que no se le puede delegar.",
|
|
34
36
|
"error.activity-approval taken by someone else": "otra persona resolvió esta aprobación antes. vuelva a cargar la lista para ver su estado.",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id} es un borrador de otra persona. Solo quien lo redactó, o quien gestiona las instancias de actividad, puede editarlo o emitirlo.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} está asignado a otro rol. solo alguien con ese rol puede seleccionarlo.",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "este hilo de tarea ({id}) está en {actual}. esta acción solo se puede realizar en {state}.",
|
|
57
59
|
"error.activity-thread should not be submitted": "este hilo de tarea ({id}) ya está en estado {actual}.",
|
|
58
60
|
"error.all activity threads should be terminated": "el hilo ({activityThread}) sigue en {state}. vuelva a intentarlo cuando todos los hilos hayan finalizado.",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats}: no hay ningún aprobador aparte de usted. añada otro aprobador a ese paso o asigne ese rol a otra persona.",
|
|
60
61
|
"error.approval line names a person who cannot be found": "{seats}: no se encuentra la persona indicada para ese paso. indique otro aprobador.",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats}: nadie tiene el rol indicado para ese paso. añada a alguien a ese rol.",
|
|
62
63
|
"error.approval-line-missing": "este formulario no tiene línea de aprobación. defina quién lo aprueba.",
|
package/translations/ja.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "修正して再申請",
|
|
3
|
+
"button.task-open-source": "元の業務を開く",
|
|
4
|
+
"text.task-source-resubmit": "元の業務で内容を修正し、新たに申請してください。却下の履歴は残ります。",
|
|
5
|
+
"text.task-abort-keeps-history": "このタスクを中止しますか?承認履歴は残り、元の業務は取り消されません。",
|
|
2
6
|
"button.try-again": "再試行",
|
|
3
7
|
"button.discard-draft": "下書きを破棄",
|
|
4
8
|
"button.abort": "中断",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "提出",
|
|
25
29
|
"button.unschedule-task": "タスクのスケジュールを解除",
|
|
26
30
|
"error.activity not found": "このタスクテンプレート({activity})が見つかりません。",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "この件は起案した方が承認できません。他に承認者がいない場合は、管理者に承認ルートへ承認者を追加するよう依頼してください。",
|
|
28
31
|
"error.activity-approval is already terminated": "この承認タスク({activityApproval})はすでに終了({actual})しています。",
|
|
29
32
|
"error.activity-approval is reference only": "参照として受け取った件のため、承認・却下はできません。意見は残せます。",
|
|
30
33
|
"error.activity-approval not found": "この承認タスク({activityApproval})が見つかりません。",
|
|
31
34
|
"error.activity-approval delegate to self": "すでにご自身の決裁です。渡す別の人を選んでください。",
|
|
32
35
|
"error.activity-approval delegate outside domain": "このサイトにいない人には渡せません。",
|
|
33
|
-
"error.activity-approval delegate to issuer": "起票した人はこの案件を承認できないため、その人には渡せません。",
|
|
34
36
|
"error.activity-approval taken by someone else": "他の方が先に処理しました。一覧を再読み込みしてください。",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id} is someone else's draft. Only the person who wrote it, or someone who manages activity instances, may edit or issue it.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} は別の役割に割り当てられた業務です。その役割を持つ人だけが選択できます。",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "この作業スレッド({id})は {actual} 状態です。{state} 状態のときだけ実行できます。",
|
|
57
59
|
"error.activity-thread should not be submitted": "このタスクスレッド({id})はすでに{actual}状態です。",
|
|
58
60
|
"error.all activity threads should be terminated": "スレッド({activityThread})がまだ {state} 状態です。すべてのスレッドが終了してから再試行してください。",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats} の段階に起案者以外の承認者がいません。別の承認者を追加するか、その役割に人を追加してください。",
|
|
60
61
|
"error.approval line names a person who cannot be found": "{seats} の段階に指定した人が見つかりません。承認者を指定し直してください。",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats} の段階に指定した役割に人がいません。その役割に人を追加してください。",
|
|
62
63
|
"error.approval-line-missing": "この様式には決裁ラインがありません。承認者を設定してください。",
|
package/translations/ko.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "수정 후 재상신",
|
|
3
|
+
"button.task-open-source": "원본 업무 열기",
|
|
4
|
+
"text.task-source-resubmit": "원본에서 내용을 수정하고 다시 상신하세요. 이전 반려 이력은 남습니다.",
|
|
5
|
+
"text.task-abort-keeps-history": "이 작업을 중단하시겠습니까? 반려·결재 이력은 남으며 원본 업무는 취소되지 않습니다.",
|
|
2
6
|
"button.try-again": "다시 시도",
|
|
3
7
|
"button.discard-draft": "초안 버리기",
|
|
4
8
|
"button.abort": "중단",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "제출",
|
|
25
29
|
"button.unschedule-task": "스케쥴 해제",
|
|
26
30
|
"error.activity not found": "이 작업템플릿({activity})을 찾을 수 없습니다.",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "상신자는 본인이 상신한 건을 결재할 수 없습니다. 다른 결재자가 없으면 관리자에게 결재자 추가를 요청해 주세요.",
|
|
28
31
|
"error.activity-approval is already terminated": "이 승인 작업({activityApproval})는 이미 종료({actual})되었습니다.",
|
|
29
32
|
"error.activity-approval is reference only": "참조로 받은 건이라 승인하거나 반려할 수 없습니다. 의견은 남길 수 있습니다.",
|
|
30
33
|
"error.activity-approval not found": "이 승인 작업({activityApproval})을 찾을 수 없습니다.",
|
|
31
34
|
"error.activity-approval delegate to self": "이미 본인에게 배정된 결재입니다. 위임할 다른 사용자를 선택해 주세요.",
|
|
32
35
|
"error.activity-approval delegate outside domain": "이 사업장에 없는 사람에게는 넘길 수 없습니다.",
|
|
33
|
-
"error.activity-approval delegate to issuer": "상신자는 본인이 상신한 건을 승인할 수 없으므로 결재를 위임받을 수 없습니다.",
|
|
34
36
|
"error.activity-approval taken by someone else": "다른 분이 먼저 처리했습니다. 목록을 새로 읽어 주십시오.",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id}은(는) 다른 사용자가 작성한 초안입니다. 작성자 또는 업무 관리자만 수정하고 제출할 수 있습니다.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} 는 다른 역할에 할당된 업무입니다. 그 역할을 가진 사람만 선택할 수 있습니다.",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "이 작업 쓰레드({id})는 {actual} 상태입니다. {state} 상태일 때만 할 수 있습니다.",
|
|
57
59
|
"error.activity-thread should not be submitted": "이 작업 쓰레드({id})는 이미 {actual} 상태입니다.",
|
|
58
60
|
"error.all activity threads should be terminated": "쓰레드({activityThread})가 아직 {state} 상태입니다. 모든 쓰레드가 종료된 뒤에 다시 시도하십시오.",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats} 단계에 기안자 말고는 결재자가 없습니다. 다른 결재자를 추가하거나 그 역할에 사람을 추가하십시오.",
|
|
60
61
|
"error.approval line names a person who cannot be found": "{seats} 단계에 지정한 사람을 찾을 수 없습니다. 결재자를 다시 지정하십시오.",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats} 단계에 지정한 역할에 사람이 없습니다. 그 역할에 사람을 추가하십시오.",
|
|
62
63
|
"error.approval-line-missing": "이 양식에 결재선이 없습니다. 결재선을 설정하십시오.",
|
package/translations/ms.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "Semak semula permohonan",
|
|
3
|
+
"button.task-open-source": "Buka kerja asal",
|
|
4
|
+
"text.task-source-resubmit": "Sunting kerja asal dan hantar permohonan baharu. Permohonan yang ditolak kekal dalam sejarah.",
|
|
5
|
+
"text.task-abort-keeps-history": "Hentikan tugas ini? Sejarah kelulusan dikekalkan dan kerja asal tidak dibatalkan.",
|
|
2
6
|
"button.try-again": "cuba lagi",
|
|
3
7
|
"button.discard-draft": "buang draf",
|
|
4
8
|
"button.abort": "batal",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "hantar",
|
|
25
29
|
"button.unschedule-task": "batalkan jadual tugas",
|
|
26
30
|
"error.activity not found": "Templat tugas ini ({activity}) tidak dijumpai.",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "anda yang mengemukakan permohonan ini, jadi orang lain perlu memutuskannya. jika tiada pelulus lain pada laluan kelulusan ini, minta pentadbir menambah pelulus.",
|
|
28
31
|
"error.activity-approval is already terminated": "Tugas kelulusan ini ({activityApproval}) telah tamat ({actual}).",
|
|
29
32
|
"error.activity-approval is reference only": "anda hanya rujukan untuk perkara ini, jadi anda tidak boleh meluluskan atau menolaknya. anda boleh meninggalkan komen.",
|
|
30
33
|
"error.activity-approval not found": "Tugas kelulusan ini ({activityApproval}) tidak dijumpai.",
|
|
31
34
|
"error.activity-approval delegate to self": "tugas ini sudah milik anda; pilih orang lain untuk diserahkan.",
|
|
32
35
|
"error.activity-approval delegate outside domain": "orang itu tiada dalam domain ini, jadi tugas tidak boleh diserahkan kepadanya.",
|
|
33
|
-
"error.activity-approval delegate to issuer": "orang yang menghantar kes ini tidak boleh meluluskannya, jadi ia tidak boleh diserahkan kepadanya.",
|
|
34
36
|
"error.activity-approval taken by someone else": "orang lain telah menguruskannya dahulu. sila muat semula senarai.",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id} is someone else's draft. Only the person who wrote it, or someone who manages activity instances, may edit or issue it.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} ditugaskan kepada peranan lain. hanya orang yang memegang peranan itu boleh memilihnya.",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "bebenang tugas ini ({id}) berstatus {actual}. ini hanya boleh dilakukan dalam status {state}.",
|
|
57
59
|
"error.activity-thread should not be submitted": "Thread tugas ini ({id}) sudah berada dalam status {actual}.",
|
|
58
60
|
"error.all activity threads should be terminated": "bebenang ({activityThread}) masih berstatus {state}. cuba lagi selepas semua bebenang ditamatkan.",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats}: tiada pelulus selain anda. tambah pelulus lain pada langkah itu, atau berikan peranan itu kepada orang lain.",
|
|
60
61
|
"error.approval line names a person who cannot be found": "{seats}: orang yang dinamakan untuk langkah itu tidak ditemui. namakan pelulus lain.",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats}: tiada sesiapa memegang peranan untuk langkah itu. tambah seseorang pada peranan itu.",
|
|
62
63
|
"error.approval-line-missing": "borang ini tiada laluan kelulusan. tetapkan siapa yang meluluskannya.",
|
package/translations/zh.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"button.revise-request": "修改后重新申请",
|
|
3
|
+
"button.task-open-source": "打开原始业务",
|
|
4
|
+
"text.task-source-resubmit": "修改原始业务后重新提交申请。驳回记录将保留。",
|
|
5
|
+
"text.task-abort-keeps-history": "停止此任务?审批历史将保留,原始业务不会被取消。",
|
|
2
6
|
"button.try-again": "重试",
|
|
3
7
|
"button.discard-draft": "丢弃草稿",
|
|
4
8
|
"button.abort": "中止",
|
|
@@ -24,13 +28,11 @@
|
|
|
24
28
|
"button.submit": "提交",
|
|
25
29
|
"button.unschedule-task": "取消安排任务",
|
|
26
30
|
"error.activity not found": "未找到此任务模板({activity})。",
|
|
27
|
-
"error.activity-approval cannot be judged by the person who raised it": "本件由您提出,需由他人审批。若此审批路径上没有其他审批人,请联系管理员添加审批人。",
|
|
28
31
|
"error.activity-approval is already terminated": "此批准任务({activityApproval})已被终止({actual})。",
|
|
29
32
|
"error.activity-approval is reference only": "此事项是抄送给您的,无法批准或驳回。可以留下意见。",
|
|
30
33
|
"error.activity-approval not found": "未找到此批准任务({activityApproval})。",
|
|
31
34
|
"error.activity-approval delegate to self": "这已经是您的审批,请选择其他人转交。",
|
|
32
35
|
"error.activity-approval delegate outside domain": "不能转交给不在本站点的人。",
|
|
33
|
-
"error.activity-approval delegate to issuer": "提交人不能审批此事项,因此不能转交给提交人。",
|
|
34
36
|
"error.activity-approval taken by someone else": "他人已先行处理,请重新加载列表。",
|
|
35
37
|
"error.activity-instance belongs to someone else": "{id} is someone else's draft. Only the person who wrote it, or someone who manages activity instances, may edit or issue it.",
|
|
36
38
|
"error.activity-instance is addressed to another role": "{id} 已分配给其他角色。只有拥有该角色的人员才能选择。",
|
|
@@ -56,7 +58,6 @@
|
|
|
56
58
|
"error.activity-thread should be the state": "此任务线程({id})处于 {actual} 状态。只能在 {state} 状态下执行。",
|
|
57
59
|
"error.activity-thread should not be submitted": "此任务线程({id})已处于{actual}状态。",
|
|
58
60
|
"error.all activity threads should be terminated": "线程({activityThread})仍处于 {state} 状态。请在所有线程结束后重试。",
|
|
59
|
-
"error.approval line has nobody but the person raising it": "{seats} 步骤中除提交人外没有审批人。请添加其他审批人,或为该角色添加人员。",
|
|
60
61
|
"error.approval line names a person who cannot be found": "找不到 {seats} 步骤指定的人员。请重新指定审批人。",
|
|
61
62
|
"error.approval line names a role that nobody holds": "{seats} 步骤指定的角色中没有人员。请为该角色添加人员。",
|
|
62
63
|
"error.approval-line-missing": "此表单没有审批线。请设置审批人。",
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 상신한 사람은 자기 상신의 결재자가 될 수 없다 — **한 물음, 두 자리.**
|
|
3
|
-
*
|
|
4
|
-
* ── 왜 규칙이 필요한가 (ADR-0052, 2026-09-16) ─────────────────────────────
|
|
5
|
-
* plant 의 「정비 완료 확인」은 상신에 `maintenance:mutation` 이 필요하고 결재선이 `MAINTENANCE-LEAD`
|
|
6
|
-
* 한 단계인데, 그 권한을 보전팀장과 정비원이 **둘 다** 든다. 정비원이 끝내고 팀장이 확인하면 두 사람이지만,
|
|
7
|
-
* **팀장이 직접 고치고 자기가 확인하면 한 사람**이다. 결재선을 고쳐서는 못 막는다 — 팀장을 빼면 정비가
|
|
8
|
-
* 끝났는지 아는 유일한 자리가 사라진다. 그날 그 사람이 둘 다인 것이 문제라 실행 시점에 막는다.
|
|
9
|
-
*
|
|
10
|
-
* ── 왜 `creator` 가 아니라 `issuer` 인가 ──────────────────────────────────
|
|
11
|
-
* 두 칸이 갈리는 길이 있다. `issue()` 는 `creator: user` 를 먼저 적고 `...origin` 으로 draft 를 펼치는데,
|
|
12
|
-
* `origin` 이 `creator` 를 관계로 싣고 있어 **덮인다.** `issuer: user` 는 그 뒤라 안 덮인다. 그리고
|
|
13
|
-
* `assertMayWorkOnDraft` 가 매니저에게 남의 draft 상신을 허용하므로, 매니저가 정비원의 draft 를 올리면
|
|
14
|
-
* creator 는 정비원이고 issuer 는 매니저다.
|
|
15
|
-
*
|
|
16
|
-
* 그때 `creator` 로 막으면 **올리지 않은 사람을 막고, 실제로 올린 사람은 자기 상신을 결재한다** — 규칙이
|
|
17
|
-
* 정확히 거꾸로 선다. 상신은 올리는 행위이고 그 판단에 책임지는 사람이 `issuer` 다. 직접 상신이면 둘이
|
|
18
|
-
* 같으므로 흔한 경우는 달라지지 않는다. (2026-09-16, 아키텍트 판정)
|
|
19
|
-
*
|
|
20
|
-
* ── 참조는 막지 않는다 ───────────────────────────────────────────────────
|
|
21
|
-
* 규칙이 막는 것은 **결재자** 자리다. 참조는 판정하지 않으므로 자기가 올린 건에 의견을 남기는 것이 이상하지
|
|
22
|
-
* 않다 — 오히려 상신한 사람이 덧붙이는 말이 결재자에게 쓸모 있다.
|
|
23
|
-
*
|
|
24
|
-
* ── 두 자리가 같은 것을 봐야 한다 ────────────────────────────────────────
|
|
25
|
-
* 누르는 자리(`checkAuthority`)와 목록에 담는 자리(`myPendingApprovalsWhere`)가 갈리면 **목록에 떴는데
|
|
26
|
-
* 누르면 거절된다.** 그것이 결함이다. 한쪽은 JS 로 묻고 다른 쪽은 SQL 로 물어야 해서 코드를 그대로 나눌
|
|
27
|
-
* 수는 없으므로, 두 표현을 이 파일에 나란히 두고 시험이 둘이 같은 칸을 본다는 것을 센다.
|
|
28
|
-
*/
|
|
29
|
-
/** 이 사람이 이 건을 올렸나. 상신자가 없는 건(`issuer` 가 빈 옛 행)은 아무도 막지 않는다. */
|
|
30
|
-
export declare function raisedIt(issuerId: string | undefined | null, userId: string | undefined | null): boolean;
|
|
31
|
-
/** 이 자리가 판정하는 자리인가 — 빈 값은 결재다(`ApprovalLineItem.participation` 과 같은 규약). */
|
|
32
|
-
export declare function judges(participation: string | undefined | null): boolean;
|
|
33
|
-
/**
|
|
34
|
-
* 거절하나 — **판단은 이 함수가 한다.**
|
|
35
|
-
*
|
|
36
|
-
* `checkAuthority` 안에 두면 시험이 못 든다. 그 파일은 엔티티를 끌어오고 엔티티는 type-graphql 을
|
|
37
|
-
* 끌어와서, 시험 러너가 파일을 여는 순간 죽는다. 그래서 거기에 남겨 두면 **원문을 읽는 시험밖에** 못
|
|
38
|
-
* 쓰게 되고, 원문 시험은 「그 글자가 있나」를 셀 뿐 「그래서 거절하나」를 못 센다.
|
|
39
|
-
*
|
|
40
|
-
* 값만 받는 함수로 빼면 네 갈래를 다 돌려 볼 수 있다 — 결재 자리 · 참조 자리 × 상신자 · 아닌 사람.
|
|
41
|
-
* 부르는 쪽에 남는 것은 값을 **가져오는** 일뿐이고, 그건 원문으로 확인해도 되는 종류다.
|
|
42
|
-
*/
|
|
43
|
-
export declare function refuseToJudge({ participation, issuerId, userId }: {
|
|
44
|
-
participation?: string | null;
|
|
45
|
-
issuerId?: string | null;
|
|
46
|
-
userId?: string | null;
|
|
47
|
-
}): boolean;
|
|
48
|
-
/**
|
|
49
|
-
* 같은 물음의 SQL — **`ai`(ActivityInstance)를 조인한 질의에서만** 쓴다.
|
|
50
|
-
*
|
|
51
|
-
* `ai.issuer != :userId` 만 쓰면 상신자가 빈 행이 SQL 의 NULL 셈법으로 조용히 빠진다 — 참이 아니라
|
|
52
|
-
* 알 수 없음이 되고, 그 행들이 아무의 결재함에도 안 뜬다. 그래서 빈 것을 먼저 통과시킨다.
|
|
53
|
-
*
|
|
54
|
-
* 참조 자리는 이 조각이 다루지 않는다. 목록 질의는 참조를 이미 앞에서 걸러 낸다.
|
|
55
|
-
*/
|
|
56
|
-
export declare const NOT_RAISED_BY_ME_SQL = "(ai.issuer IS NULL OR ai.issuer != :userId)";
|
|
57
|
-
/**
|
|
58
|
-
* 상신한 사람이 결재하려 했다 — **커널이 쓰는 낱말과 같은 값이어야 한다.**
|
|
59
|
-
*
|
|
60
|
-
* `headless-twin/server/service/actuation/command-dispatcher.ts` 의 `SELF_APPROVAL` 과 짝이다.
|
|
61
|
-
* **두 벌이 아니라 두 문이다** — 커널은 업무 목록을 안 지나는 길(API · AI 발의)에서 자기 커맨드를
|
|
62
|
-
* 지키고, 여기는 결재 문을 지킨다. 커널↔호스트 경계를 넘어 합치지 않는다.
|
|
63
|
-
*
|
|
64
|
-
* 두 문이 위험한 것은 **서로 다른 답을 낼 때**다. 그래서 문장이 아니라 코드를 맞춘다 — 문장은 번역도
|
|
65
|
-
* 집계도 안 되고, 고치는 날 두 문이 다른 말을 한다. 상수를 서로 import 하면 두 패키지가 묶이므로,
|
|
66
|
-
* **양쪽이 각자 글자를 시험에 못 박는다.** 그래야 움직인 쪽이 빨개진다. (ADR-0052 ③)
|
|
67
|
-
*
|
|
68
|
-
* ⚠ 아래 `only-the-issuer-could-judge` 와 **다른 사실**이다. 이쪽은 「결재하려 한다」이고 그쪽은
|
|
69
|
-
* 「설 사람이 상신자뿐이라 못 올린다」다. 글자 모양이 눈에 띄게 다른 것도 일부러다.
|
|
70
|
-
*/
|
|
71
|
-
export declare const SELF_APPROVAL = "self-approval";
|
|
72
|
-
/** 거절할 때 쓰는 키 — 무엇을 해야 하는지까지 문구가 말한다. */
|
|
73
|
-
export declare const OWN_REQUEST_REFUSAL_KEY = "error.activity-approval cannot be judged by the person who raised it";
|
|
74
|
-
/** 사람에게는 문장을, 붙잡는 쪽에는 `code` 를 준다 — 커널이 같은 모양으로 던진다. */
|
|
75
|
-
export declare function selfApprovalRefused(said: string): Error & {
|
|
76
|
-
code: string;
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* ═══════════════════════════════════════════════════════════════════════════
|
|
80
|
-
* 같은 규칙을 **상신하는 순간**에 본다 — 누르는 순간에 거절만 하면 멈춘다.
|
|
81
|
-
* ═══════════════════════════════════════════════════════════════════════════
|
|
82
|
-
*
|
|
83
|
-
* 위의 `refuseToJudge` 는 자기 상신을 결재하려는 사람을 막는다. 그것만 세우면 **결재선에 그 사람밖에
|
|
84
|
-
* 없는 건이 아무에게도 안 간다.** 정비 완료 확인이 그 모양이면 설비가 정비중으로 남고 그 라인이 선다.
|
|
85
|
-
* 시드 주석이 걱정한 것이 이것이다.
|
|
86
|
-
*
|
|
87
|
-
* 그래서 올리는 자리에서 먼저 본다. 올릴 때 막으면 **고칠 수 있는 사람이 보는 자리**에서 걸리고,
|
|
88
|
-
* 무엇을 고쳐야 하는지 그 자리에서 말할 수 있다. 결재 중에 걸리면 이미 설비가 멈춘 뒤다.
|
|
89
|
-
* (2026-09-16, ADR-0052 ② · 아키텍트 판정 (다))
|
|
90
|
-
*
|
|
91
|
-
* ── 왜 「한 자리라도」가 아니라 「모든 자리」인가 ──────────────────────────
|
|
92
|
-
* 결재선의 결재 자리는 차례로 **전부** 판정을 받아야 끝난다. 한 자리만 막혀도 그 건은 거기서 영영
|
|
93
|
-
* 선다. 그래서 자리마다 본다.
|
|
94
|
-
*
|
|
95
|
-
* ── 아무도 못 서는 자리는 **같은 관문에서 다른 낱말로** 거절한다 ──────────
|
|
96
|
-
* 그 역할을 가진 사람이 **하나도 없는** 자리도 똑같이 건을 멈춘다. 그런데 상신자 탓이 아니므로,
|
|
97
|
-
* 같은 사유로 묶으면 「당신이 올려서 막혔다」는 **틀린 이유**를 대게 된다.
|
|
98
|
-
*
|
|
99
|
-
* 자리가 같다고 사유를 합치지 않는다 — **관리자가 할 일이 다르다.** 하나는 「그 자리에 다른 결재자를」
|
|
100
|
-
* 이고 하나는 「그 역할에 사람을」이다. 낱말은 이미 있다: `approval-role-empty`(ADR-0047 ②).
|
|
101
|
-
* (2026-09-16, 아키텍트 판정)
|
|
102
|
-
*
|
|
103
|
-
* 사람 자리가 **아무에게도 안 풀리는** 경우도 같은 자리에서 세 번째 낱말로 거절한다 — 없어진 직원을
|
|
104
|
-
* 가리키는 자리다. 역할 문제가 아니므로 `approval-role-empty` 로 부르면 그것도 틀린 이유다.
|
|
105
|
-
* 세 낱말이 자리를 선언하는 세 방법을 그대로 따른다:
|
|
106
|
-
*
|
|
107
|
-
* approval-line-missing 결재선 자체가 없다 (§`approval-expectation.ts`)
|
|
108
|
-
* approval-role-empty 지목한 역할에 사람이 0명
|
|
109
|
-
* approval-person-missing 지목한 사람 자리가 안 풀린다
|
|
110
|
-
*
|
|
111
|
-
* 전에는 `submit` 이 `error.approver is not set on the approval line` 로 잡았는데, 그때는 이미 올라간
|
|
112
|
-
* 뒤다. (2026-09-16, 아키텍트 판정)
|
|
113
|
-
*/
|
|
114
|
-
/** 결재 자리 하나와, 거기 설 수 있는 사람들. 역할 자리면 그 역할을 가진 사람 전부. */
|
|
115
|
-
export type JudgeableSeat = {
|
|
116
|
-
/** 사람이 세는 차례 — 1차 결재, 2차 결재. 거절 문구가 이 수를 말한다. */
|
|
117
|
-
order: number;
|
|
118
|
-
/** 역할로 건 자리인가 사람으로 건 자리인가 — **거절 사유가 갈린다.** */
|
|
119
|
-
kind: 'role' | 'person';
|
|
120
|
-
/** 그 자리에 설 수 있는 사람들의 id. 역할 자리면 그 역할을 가진 사람 전부. */
|
|
121
|
-
couldJudge: string[];
|
|
122
|
-
/** 화면에 낼 자리 이름 — 역할 이름이나 사람 이름. */
|
|
123
|
-
name?: string;
|
|
124
|
-
/**
|
|
125
|
-
* 그 자리가 **가리키던 식별자.** 안 풀리는 자리를 고치려면 「누구 자리였는지」를 알아야 한다 —
|
|
126
|
-
* 이름은 못 찾으면 비는데 가리키던 값은 결재선에 그대로 남아 있다.
|
|
127
|
-
*/
|
|
128
|
-
pointsAt?: string;
|
|
129
|
-
};
|
|
130
|
-
/** 거절 사유 하나와, 그 사유로 막힌 자리들. */
|
|
131
|
-
export type SeatRefusal = {
|
|
132
|
-
because: 'only-the-issuer-could-judge' | 'approval-role-empty' | 'approval-person-missing';
|
|
133
|
-
seats: {
|
|
134
|
-
order: number;
|
|
135
|
-
name?: string;
|
|
136
|
-
pointsAt?: string;
|
|
137
|
-
}[];
|
|
138
|
-
};
|
|
139
|
-
export type StandingVerdict = {
|
|
140
|
-
ok: true;
|
|
141
|
-
} | {
|
|
142
|
-
ok: false;
|
|
143
|
-
refusals: SeatRefusal[];
|
|
144
|
-
};
|
|
145
|
-
/**
|
|
146
|
-
* 이 결재선을 이 사람이 올려도 되나.
|
|
147
|
-
*
|
|
148
|
-
* 사유가 둘이면 **둘 다 돌려준다.** 하나씩 말하면 관리자가 하나 고치고 다시 걸린다 — 자리를 전부
|
|
149
|
-
* 말하는 것과 같은 이유다.
|
|
150
|
-
*/
|
|
151
|
-
export declare function judgeSomeoneElseCanJudge(input: {
|
|
152
|
-
issuerId?: string | null;
|
|
153
|
-
/** **결재 자리만.** 참조는 판정하지 않으므로 여기 오지 않는다. */
|
|
154
|
-
seats: JudgeableSeat[];
|
|
155
|
-
}): StandingVerdict;
|
|
156
|
-
export declare function standingBroken(verdict: StandingVerdict): verdict is Extract<StandingVerdict, {
|
|
157
|
-
ok: false;
|
|
158
|
-
}>;
|
|
159
|
-
/** 사유마다 문구가 다르다 — 관리자가 할 일이 다르기 때문이다. */
|
|
160
|
-
export declare const STANDING_REFUSAL_KEYS: {
|
|
161
|
-
[because in SeatRefusal['because']]: string;
|
|
162
|
-
};
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* 상신한 사람은 자기 상신의 결재자가 될 수 없다 — **한 물음, 두 자리.**
|
|
4
|
-
*
|
|
5
|
-
* ── 왜 규칙이 필요한가 (ADR-0052, 2026-09-16) ─────────────────────────────
|
|
6
|
-
* plant 의 「정비 완료 확인」은 상신에 `maintenance:mutation` 이 필요하고 결재선이 `MAINTENANCE-LEAD`
|
|
7
|
-
* 한 단계인데, 그 권한을 보전팀장과 정비원이 **둘 다** 든다. 정비원이 끝내고 팀장이 확인하면 두 사람이지만,
|
|
8
|
-
* **팀장이 직접 고치고 자기가 확인하면 한 사람**이다. 결재선을 고쳐서는 못 막는다 — 팀장을 빼면 정비가
|
|
9
|
-
* 끝났는지 아는 유일한 자리가 사라진다. 그날 그 사람이 둘 다인 것이 문제라 실행 시점에 막는다.
|
|
10
|
-
*
|
|
11
|
-
* ── 왜 `creator` 가 아니라 `issuer` 인가 ──────────────────────────────────
|
|
12
|
-
* 두 칸이 갈리는 길이 있다. `issue()` 는 `creator: user` 를 먼저 적고 `...origin` 으로 draft 를 펼치는데,
|
|
13
|
-
* `origin` 이 `creator` 를 관계로 싣고 있어 **덮인다.** `issuer: user` 는 그 뒤라 안 덮인다. 그리고
|
|
14
|
-
* `assertMayWorkOnDraft` 가 매니저에게 남의 draft 상신을 허용하므로, 매니저가 정비원의 draft 를 올리면
|
|
15
|
-
* creator 는 정비원이고 issuer 는 매니저다.
|
|
16
|
-
*
|
|
17
|
-
* 그때 `creator` 로 막으면 **올리지 않은 사람을 막고, 실제로 올린 사람은 자기 상신을 결재한다** — 규칙이
|
|
18
|
-
* 정확히 거꾸로 선다. 상신은 올리는 행위이고 그 판단에 책임지는 사람이 `issuer` 다. 직접 상신이면 둘이
|
|
19
|
-
* 같으므로 흔한 경우는 달라지지 않는다. (2026-09-16, 아키텍트 판정)
|
|
20
|
-
*
|
|
21
|
-
* ── 참조는 막지 않는다 ───────────────────────────────────────────────────
|
|
22
|
-
* 규칙이 막는 것은 **결재자** 자리다. 참조는 판정하지 않으므로 자기가 올린 건에 의견을 남기는 것이 이상하지
|
|
23
|
-
* 않다 — 오히려 상신한 사람이 덧붙이는 말이 결재자에게 쓸모 있다.
|
|
24
|
-
*
|
|
25
|
-
* ── 두 자리가 같은 것을 봐야 한다 ────────────────────────────────────────
|
|
26
|
-
* 누르는 자리(`checkAuthority`)와 목록에 담는 자리(`myPendingApprovalsWhere`)가 갈리면 **목록에 떴는데
|
|
27
|
-
* 누르면 거절된다.** 그것이 결함이다. 한쪽은 JS 로 묻고 다른 쪽은 SQL 로 물어야 해서 코드를 그대로 나눌
|
|
28
|
-
* 수는 없으므로, 두 표현을 이 파일에 나란히 두고 시험이 둘이 같은 칸을 본다는 것을 센다.
|
|
29
|
-
*/
|
|
30
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.STANDING_REFUSAL_KEYS = exports.OWN_REQUEST_REFUSAL_KEY = exports.SELF_APPROVAL = exports.NOT_RAISED_BY_ME_SQL = void 0;
|
|
32
|
-
exports.raisedIt = raisedIt;
|
|
33
|
-
exports.judges = judges;
|
|
34
|
-
exports.refuseToJudge = refuseToJudge;
|
|
35
|
-
exports.selfApprovalRefused = selfApprovalRefused;
|
|
36
|
-
exports.judgeSomeoneElseCanJudge = judgeSomeoneElseCanJudge;
|
|
37
|
-
exports.standingBroken = standingBroken;
|
|
38
|
-
/** 이 사람이 이 건을 올렸나. 상신자가 없는 건(`issuer` 가 빈 옛 행)은 아무도 막지 않는다. */
|
|
39
|
-
function raisedIt(issuerId, userId) {
|
|
40
|
-
return !!issuerId && !!userId && issuerId === userId;
|
|
41
|
-
}
|
|
42
|
-
/** 이 자리가 판정하는 자리인가 — 빈 값은 결재다(`ApprovalLineItem.participation` 과 같은 규약). */
|
|
43
|
-
function judges(participation) {
|
|
44
|
-
return participation !== 'reference';
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* 거절하나 — **판단은 이 함수가 한다.**
|
|
48
|
-
*
|
|
49
|
-
* `checkAuthority` 안에 두면 시험이 못 든다. 그 파일은 엔티티를 끌어오고 엔티티는 type-graphql 을
|
|
50
|
-
* 끌어와서, 시험 러너가 파일을 여는 순간 죽는다. 그래서 거기에 남겨 두면 **원문을 읽는 시험밖에** 못
|
|
51
|
-
* 쓰게 되고, 원문 시험은 「그 글자가 있나」를 셀 뿐 「그래서 거절하나」를 못 센다.
|
|
52
|
-
*
|
|
53
|
-
* 값만 받는 함수로 빼면 네 갈래를 다 돌려 볼 수 있다 — 결재 자리 · 참조 자리 × 상신자 · 아닌 사람.
|
|
54
|
-
* 부르는 쪽에 남는 것은 값을 **가져오는** 일뿐이고, 그건 원문으로 확인해도 되는 종류다.
|
|
55
|
-
*/
|
|
56
|
-
function refuseToJudge({ participation, issuerId, userId }) {
|
|
57
|
-
return judges(participation) && raisedIt(issuerId, userId);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* 같은 물음의 SQL — **`ai`(ActivityInstance)를 조인한 질의에서만** 쓴다.
|
|
61
|
-
*
|
|
62
|
-
* `ai.issuer != :userId` 만 쓰면 상신자가 빈 행이 SQL 의 NULL 셈법으로 조용히 빠진다 — 참이 아니라
|
|
63
|
-
* 알 수 없음이 되고, 그 행들이 아무의 결재함에도 안 뜬다. 그래서 빈 것을 먼저 통과시킨다.
|
|
64
|
-
*
|
|
65
|
-
* 참조 자리는 이 조각이 다루지 않는다. 목록 질의는 참조를 이미 앞에서 걸러 낸다.
|
|
66
|
-
*/
|
|
67
|
-
exports.NOT_RAISED_BY_ME_SQL = '(ai.issuer IS NULL OR ai.issuer != :userId)';
|
|
68
|
-
/**
|
|
69
|
-
* 상신한 사람이 결재하려 했다 — **커널이 쓰는 낱말과 같은 값이어야 한다.**
|
|
70
|
-
*
|
|
71
|
-
* `headless-twin/server/service/actuation/command-dispatcher.ts` 의 `SELF_APPROVAL` 과 짝이다.
|
|
72
|
-
* **두 벌이 아니라 두 문이다** — 커널은 업무 목록을 안 지나는 길(API · AI 발의)에서 자기 커맨드를
|
|
73
|
-
* 지키고, 여기는 결재 문을 지킨다. 커널↔호스트 경계를 넘어 합치지 않는다.
|
|
74
|
-
*
|
|
75
|
-
* 두 문이 위험한 것은 **서로 다른 답을 낼 때**다. 그래서 문장이 아니라 코드를 맞춘다 — 문장은 번역도
|
|
76
|
-
* 집계도 안 되고, 고치는 날 두 문이 다른 말을 한다. 상수를 서로 import 하면 두 패키지가 묶이므로,
|
|
77
|
-
* **양쪽이 각자 글자를 시험에 못 박는다.** 그래야 움직인 쪽이 빨개진다. (ADR-0052 ③)
|
|
78
|
-
*
|
|
79
|
-
* ⚠ 아래 `only-the-issuer-could-judge` 와 **다른 사실**이다. 이쪽은 「결재하려 한다」이고 그쪽은
|
|
80
|
-
* 「설 사람이 상신자뿐이라 못 올린다」다. 글자 모양이 눈에 띄게 다른 것도 일부러다.
|
|
81
|
-
*/
|
|
82
|
-
exports.SELF_APPROVAL = 'self-approval';
|
|
83
|
-
/** 거절할 때 쓰는 키 — 무엇을 해야 하는지까지 문구가 말한다. */
|
|
84
|
-
exports.OWN_REQUEST_REFUSAL_KEY = 'error.activity-approval cannot be judged by the person who raised it';
|
|
85
|
-
/** 사람에게는 문장을, 붙잡는 쪽에는 `code` 를 준다 — 커널이 같은 모양으로 던진다. */
|
|
86
|
-
function selfApprovalRefused(said) {
|
|
87
|
-
const error = new Error(said);
|
|
88
|
-
error.code = exports.SELF_APPROVAL;
|
|
89
|
-
return error;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* 이 결재선을 이 사람이 올려도 되나.
|
|
93
|
-
*
|
|
94
|
-
* 사유가 둘이면 **둘 다 돌려준다.** 하나씩 말하면 관리자가 하나 고치고 다시 걸린다 — 자리를 전부
|
|
95
|
-
* 말하는 것과 같은 이유다.
|
|
96
|
-
*/
|
|
97
|
-
function judgeSomeoneElseCanJudge(input) {
|
|
98
|
-
const { issuerId, seats } = input;
|
|
99
|
-
const named = (of) => of.map(({ order, name, pointsAt }) => ({ order, name, pointsAt }));
|
|
100
|
-
/* 역할을 지목했는데 그 역할에 사람이 없다 — 상신자가 누구든 이 자리는 아무도 못 선다. */
|
|
101
|
-
const roleEmpty = seats.filter(seat => seat.kind === 'role' && seat.couldJudge.length === 0);
|
|
102
|
-
/*
|
|
103
|
-
* 설 수 있는 사람이 있는데 그게 상신자뿐이다. 상신자를 모르면 이 사유는 성립하지 않는다 —
|
|
104
|
-
* 「없음」을 「그 사람」으로 읽지 않는다.
|
|
105
|
-
*/
|
|
106
|
-
const onlyIssuer = issuerId
|
|
107
|
-
? seats.filter(seat => seat.couldJudge.length > 0 && seat.couldJudge.every(one => one === issuerId))
|
|
108
|
-
: [];
|
|
109
|
-
/*
|
|
110
|
-
* 지목한 사람이 안 풀린다 — 없어진 직원을 가리키는 자리다. 역할 문제가 아니므로 위와 다른 낱말이다.
|
|
111
|
-
* 세 낱말이 자리를 선언하는 세 방법을 그대로 따른다: line · role · person.
|
|
112
|
-
*/
|
|
113
|
-
const personMissing = seats.filter(seat => seat.kind === 'person' && seat.couldJudge.length === 0);
|
|
114
|
-
const refusals = [];
|
|
115
|
-
if (onlyIssuer.length) {
|
|
116
|
-
refusals.push({ because: 'only-the-issuer-could-judge', seats: named(onlyIssuer) });
|
|
117
|
-
}
|
|
118
|
-
if (roleEmpty.length) {
|
|
119
|
-
refusals.push({ because: 'approval-role-empty', seats: named(roleEmpty) });
|
|
120
|
-
}
|
|
121
|
-
if (personMissing.length) {
|
|
122
|
-
refusals.push({ because: 'approval-person-missing', seats: named(personMissing) });
|
|
123
|
-
}
|
|
124
|
-
return refusals.length ? { ok: false, refusals } : { ok: true };
|
|
125
|
-
}
|
|
126
|
-
function standingBroken(verdict) {
|
|
127
|
-
return !verdict.ok;
|
|
128
|
-
}
|
|
129
|
-
/** 사유마다 문구가 다르다 — 관리자가 할 일이 다르기 때문이다. */
|
|
130
|
-
exports.STANDING_REFUSAL_KEYS = {
|
|
131
|
-
'only-the-issuer-could-judge': 'error.approval line has nobody but the person raising it',
|
|
132
|
-
'approval-role-empty': 'error.approval line names a role that nobody holds',
|
|
133
|
-
'approval-person-missing': 'error.approval line names a person who cannot be found'
|
|
134
|
-
};
|
|
135
|
-
//# sourceMappingURL=own-request.js.map
|