@things-factory/worklist 10.1.198 → 10.1.203

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.
Files changed (124) hide show
  1. package/dist-client/components/activity-thread-timeline.d.ts +2 -2
  2. package/dist-client/pages/activity/activity-list-page.d.ts +3 -0
  3. package/dist-client/pages/activity/activity-list-page.js +25 -13
  4. package/dist-client/pages/activity/activity-list-page.js.map +1 -1
  5. package/dist-client/pages/activity/activity-partial-view.js +1 -1
  6. package/dist-client/pages/activity/activity-partial-view.js.map +1 -1
  7. package/dist-client/pages/activity/assignee-roles-cell.d.ts +32 -0
  8. package/dist-client/pages/activity/assignee-roles-cell.js +26 -0
  9. package/dist-client/pages/activity/assignee-roles-cell.js.map +1 -0
  10. package/dist-client/pages/activity-catalog/activity-catalog-page.js +1 -1
  11. package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
  12. package/dist-client/pages/activity-instance/activity-instance-view.d.ts +1 -1
  13. package/dist-client/pages/activity-thread/activity-thread-view.d.ts +1 -1
  14. package/dist-client/pages/work-door/door-sentence.d.ts +1 -1
  15. package/dist-client/pages/work-door/door-sentence.js +2 -2
  16. package/dist-client/pages/work-door/door-sentence.js.map +1 -1
  17. package/dist-client/route.d.ts +1 -1
  18. package/dist-client/tsconfig.tsbuildinfo +1 -1
  19. package/dist-client/types/activity-instance-type.d.ts +2 -2
  20. package/dist-client/types/activity-instance-type.js.map +1 -1
  21. package/dist-client/types/activity-instance.d.ts +1 -1
  22. package/dist-client/types/activity-instance.js.map +1 -1
  23. package/dist-client/types/activity.d.ts +1 -1
  24. package/dist-client/types/activity.js.map +1 -1
  25. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.d.ts +2 -2
  26. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js +2 -2
  27. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js.map +1 -1
  28. package/dist-server/controllers/activity-instance/abort.js +1 -1
  29. package/dist-server/controllers/activity-instance/abort.js.map +1 -1
  30. package/dist-server/controllers/activity-instance/assign.d.ts +2 -1
  31. package/dist-server/controllers/activity-instance/assign.js +104 -2
  32. package/dist-server/controllers/activity-instance/assign.js.map +1 -1
  33. package/dist-server/controllers/activity-instance/assignee-input.d.ts +25 -0
  34. package/dist-server/controllers/activity-instance/assignee-input.js +28 -0
  35. package/dist-server/controllers/activity-instance/assignee-input.js.map +1 -0
  36. package/dist-server/controllers/activity-instance/draft.js +7 -2
  37. package/dist-server/controllers/activity-instance/draft.js.map +1 -1
  38. package/dist-server/controllers/activity-instance/end.js +1 -1
  39. package/dist-server/controllers/activity-instance/end.js.map +1 -1
  40. package/dist-server/controllers/activity-instance/entitlement.d.ts +1 -1
  41. package/dist-server/controllers/activity-instance/entitlement.js +7 -5
  42. package/dist-server/controllers/activity-instance/entitlement.js.map +1 -1
  43. package/dist-server/controllers/activity-instance/issue.js +28 -7
  44. package/dist-server/controllers/activity-instance/issue.js.map +1 -1
  45. package/dist-server/controllers/activity-instance/pick.js +22 -3
  46. package/dist-server/controllers/activity-instance/pick.js.map +1 -1
  47. package/dist-server/controllers/activity-read/assert-may-read.js +2 -1
  48. package/dist-server/controllers/activity-read/assert-may-read.js.map +1 -1
  49. package/dist-server/controllers/activity-read/participates.d.ts +2 -2
  50. package/dist-server/controllers/activity-read/participates.js +2 -2
  51. package/dist-server/controllers/activity-read/participates.js.map +1 -1
  52. package/dist-server/controllers/activity-thread/check-authority.js +22 -4
  53. package/dist-server/controllers/activity-thread/check-authority.js.map +1 -1
  54. package/dist-server/controllers/common.js +17 -12
  55. package/dist-server/controllers/common.js.map +1 -1
  56. package/dist-server/service/activity/activity-history.d.ts +1 -2
  57. package/dist-server/service/activity/activity-history.js +4 -8
  58. package/dist-server/service/activity/activity-history.js.map +1 -1
  59. package/dist-server/service/activity/activity-mutation.js +39 -8
  60. package/dist-server/service/activity/activity-mutation.js.map +1 -1
  61. package/dist-server/service/activity/activity-query.d.ts +1 -1
  62. package/dist-server/service/activity/activity-query.js +9 -9
  63. package/dist-server/service/activity/activity-query.js.map +1 -1
  64. package/dist-server/service/activity/activity-type.d.ts +2 -2
  65. package/dist-server/service/activity/activity-type.js +12 -6
  66. package/dist-server/service/activity/activity-type.js.map +1 -1
  67. package/dist-server/service/activity/activity.d.ts +2 -2
  68. package/dist-server/service/activity/activity.js +15 -7
  69. package/dist-server/service/activity/activity.js.map +1 -1
  70. package/dist-server/service/activity/event-subscriber.js.map +1 -1
  71. package/dist-server/service/activity-instance/activity-instance-history.d.ts +1 -2
  72. package/dist-server/service/activity-instance/activity-instance-history.js +4 -8
  73. package/dist-server/service/activity-instance/activity-instance-history.js.map +1 -1
  74. package/dist-server/service/activity-instance/activity-instance-mutation.d.ts +1 -1
  75. package/dist-server/service/activity-instance/activity-instance-mutation.js +10 -5
  76. package/dist-server/service/activity-instance/activity-instance-mutation.js.map +1 -1
  77. package/dist-server/service/activity-instance/activity-instance-query.d.ts +1 -2
  78. package/dist-server/service/activity-instance/activity-instance-query.js +16 -25
  79. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  80. package/dist-server/service/activity-instance/activity-instance-type.d.ts +2 -2
  81. package/dist-server/service/activity-instance/activity-instance-type.js +12 -6
  82. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  83. package/dist-server/service/activity-instance/activity-instance.d.ts +2 -2
  84. package/dist-server/service/activity-instance/activity-instance.js +15 -7
  85. package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
  86. package/dist-server/service/activity-instance/assignee-pool.d.ts +59 -0
  87. package/dist-server/service/activity-instance/assignee-pool.js +99 -0
  88. package/dist-server/service/activity-instance/assignee-pool.js.map +1 -0
  89. package/dist-server/service/activity-instance/event-subscriber.d.ts +9 -1
  90. package/dist-server/service/activity-instance/event-subscriber.js +20 -4
  91. package/dist-server/service/activity-instance/event-subscriber.js.map +1 -1
  92. package/dist-server/service/activity-summary/activity-summary-query.js +3 -3
  93. package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
  94. package/dist-server/service/activity-thread/my-open-threads.d.ts +1 -1
  95. package/dist-server/service/activity-thread/my-open-threads.js +4 -3
  96. package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
  97. package/dist-server/service/index.d.ts +1 -1
  98. package/dist-server/service/subscription/subscription-filters.d.ts +3 -2
  99. package/dist-server/service/subscription/subscription-filters.js +6 -3
  100. package/dist-server/service/subscription/subscription-filters.js.map +1 -1
  101. package/dist-server/service/work-door/work-door-service.js +9 -6
  102. package/dist-server/service/work-door/work-door-service.js.map +1 -1
  103. package/dist-server/service/work-door/work-door-type.d.ts +1 -1
  104. package/dist-server/service/work-door/work-door-type.js +4 -4
  105. package/dist-server/service/work-door/work-door-type.js.map +1 -1
  106. package/dist-server/service/work-door/work-door.d.ts +3 -3
  107. package/dist-server/service/work-door/work-door.js +2 -2
  108. package/dist-server/service/work-door/work-door.js.map +1 -1
  109. package/dist-server/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +9 -9
  111. package/tests/assign-role-pool.test.ts +508 -0
  112. package/tests/assignee-pool-history.test.ts +81 -0
  113. package/tests/may-read-case.test.ts +3 -2
  114. package/tests/org-member-domain.test.ts +10 -4
  115. package/tests/pick-race.pg.test.ts +2 -2
  116. package/tests/published-shape.test.ts +2 -2
  117. package/tests/role-pool-race.pg.test.ts +182 -0
  118. package/tests/work-door.test.ts +3 -3
  119. package/translations/en.json +5 -0
  120. package/translations/es.json +5 -0
  121. package/translations/ja.json +5 -0
  122. package/translations/ko.json +5 -0
  123. package/translations/ms.json +5 -0
  124. package/translations/zh.json +5 -0
@@ -63,7 +63,7 @@ maybe('picking at once, on postgres', () => {
63
63
  name: `p${round}`,
64
64
  state: 'issued',
65
65
  activity,
66
- assigneeRole: role,
66
+ assigneeRoles: [role],
67
67
  threadsMin: 1,
68
68
  threadsMax: 1
69
69
  })
@@ -111,7 +111,7 @@ maybe('picking at once, on postgres', () => {
111
111
  name: `two${round}`,
112
112
  state: 'issued',
113
113
  activity,
114
- assigneeRole: role,
114
+ assigneeRoles: [role],
115
115
  threadsMin: 2,
116
116
  threadsMax: 2
117
117
  })
@@ -54,9 +54,9 @@ beforeEach(() => (seen.length = 0))
54
54
  const handed = (name: string, on: string) => seen.find(one => one.name === name && one.on === on)?.entity
55
55
 
56
56
  it('a new instance carries its domain, its maker and the role it waits for', async () => {
57
- await db.getRepository(ActivityInstance).save({ domain, name: 'i', creator: user, assigneeRole: role, state: 'issued' })
57
+ await db.getRepository(ActivityInstance).save({ domain, name: 'i', creator: user, assigneeRoles: [role], state: 'issued' })
58
58
 
59
- expect(handed('ActivityInstance', 'insert')).toMatchObject({ domainId: domain.id, creatorId: user.id, assigneeRoleId: role.id })
59
+ expect(handed('ActivityInstance', 'insert')).toMatchObject({ domainId: domain.id, creatorId: user.id, assigneeRoleIds: [role.id] })
60
60
  })
61
61
 
62
62
  it('a new thread carries its domain and its assignee', async () => {
@@ -0,0 +1,182 @@
1
+ import { join } from 'path'
2
+
3
+ /**
4
+ * Putting a case in a role's pool at the same moment as something else, on postgres (ADR-0091 decision 9).
5
+ *
6
+ * Every way into a waiting case takes the case's row first and its threads after - pick, a pool assign,
7
+ * a member claiming the pool's waiting thread. sqlite holds one connection and cannot run two transactions
8
+ * side by side, so what it says about this is no evidence either way. Runs only when WORKLIST_PG_URL names a
9
+ * postgres server (see discard-versus-issue.pg.test.ts):
10
+ *
11
+ * docker run -d --name wl-ux-pg -e POSTGRES_PASSWORD=wlux -e POSTGRES_USER=wlux -e POSTGRES_DB=wlux \
12
+ * -p 55433:5432 postgres:14-alpine
13
+ * WORKLIST_PG_URL=postgres://wlux:wlux@localhost:55433/wlux npx jest packages/worklist/tests/role-pool-race.pg.test.ts
14
+ *
15
+ * Each round must end one way or the other, and whoever lost is refused by name - a deadlock, two waiting
16
+ * threads, a pool wiped by a stale save, or someone outside the role holding the case is the defect.
17
+ */
18
+
19
+ const url = process.env.WORKLIST_PG_URL
20
+ const maybe = url ? describe : describe.skip
21
+
22
+ /* Nobody here manages activity instances - the role is the only way in. */
23
+ jest.mock('@things-factory/auth-base', () => {
24
+ const actual = jest.requireActual('@things-factory/auth-base')
25
+ return { ...actual, checkPermission: async () => false }
26
+ })
27
+
28
+ maybe('a role pool at the same moment as something else, on postgres', () => {
29
+ const { DataSource } = require('typeorm')
30
+ const { entityClosure } = require(join(__dirname, '..', '..', 'ops-master', 'test', 'support', 'database.cjs'))
31
+ const { NamingStrategy } = require('@things-factory/shell/dist-server/initializers/naming-strategy.js')
32
+ const DIST = join(__dirname, '..', 'dist-server')
33
+ const { Activity } = require(join(DIST, 'service', 'activity', 'activity.js'))
34
+ const { ActivityInstance } = require(join(DIST, 'service', 'activity-instance', 'activity-instance.js'))
35
+ const { ActivityThread } = require(join(DIST, 'service', 'activity-thread', 'activity-thread.js'))
36
+ const { ActivityApproval } = require(join(DIST, 'service', 'activity-approval', 'activity-approval.js'))
37
+ const { assign } = require(join(DIST, 'controllers', 'activity-instance', 'assign.js'))
38
+ const { pick } = require(join(DIST, 'controllers', 'activity-instance', 'pick.js'))
39
+ const { start } = require(join(DIST, 'controllers', 'activity-thread', 'start.js'))
40
+ const { Domain } = require('@things-factory/shell')
41
+ const { Role, User } = require('@things-factory/auth-base')
42
+
43
+ /* The refusals a loser may get - by name, never a deadlock or a constraint error. */
44
+ const NAMED = [
45
+ 'error.activity-approval taken by someone else',
46
+ 'error.activity-instance is addressed to another role',
47
+ 'error.activity-instance should not be assigned',
48
+ 'error.not authorized to handle this task'
49
+ ]
50
+
51
+ let db: any
52
+ let domain: any
53
+ let manager: any
54
+ let finance: any
55
+ let support: any
56
+ let inFinance: any
57
+ let inSupport: any
58
+ let outsider: any
59
+ let activity: any
60
+
61
+ beforeAll(async () => {
62
+ db = new DataSource({
63
+ type: 'postgres',
64
+ url,
65
+ synchronize: true,
66
+ dropSchema: true,
67
+ entities: entityClosure([Activity, ActivityInstance, ActivityThread, ActivityApproval]),
68
+ namingStrategy: new NamingStrategy()
69
+ })
70
+ await db.initialize()
71
+
72
+ domain = await db.getRepository(Domain).save({ name: 'd', subdomain: 'd' })
73
+ const person = (name: string) =>
74
+ db.getRepository(User).save({ name, email: `${name}@example.com`, password: 'x', status: 'activated', userType: 'user', domains: [domain] })
75
+ manager = await person('manager')
76
+ inFinance = await person('in-finance')
77
+ inSupport = await person('in-support')
78
+ outsider = await person('outsider')
79
+ finance = await db.getRepository(Role).save({ domain, name: 'finance', users: [inFinance] })
80
+ support = await db.getRepository(Role).save({ domain, name: 'support', users: [inSupport] })
81
+ activity = await db.getRepository(Activity).save({ domain, name: 'tax-invoice', activityType: 'standard', startingType: 'issue' })
82
+ }, 60000)
83
+
84
+ afterAll(async () => db?.destroy())
85
+
86
+ const as = (user: any) => (tx: any) => ({ state: { domain, user, tx }, t: (key: string) => key }) as any
87
+ const aCase = (name: string) => db.getRepository(ActivityInstance).save({ domain, name, state: 'issued', activity })
88
+ const threadsOf = (instance: any) => db.getRepository(ActivityThread).find({ where: { activityInstance: { id: instance.id } } })
89
+ const reread = (instance: any) => db.getRepository(ActivityInstance).findOne({ where: { id: instance.id }, relations: ['assigneeRoles'] })
90
+ const poolOf = (row: any) => (row?.assigneeRoles || []).map((role: any) => role.id).sort()
91
+ const toPool = (instance: any, role: any) => (tx: any) => assign({ id: instance.id, assigneeRoles: [role.id] }, as(manager)(tx))
92
+
93
+ /** Every loser was refused by one of the named refusals. */
94
+ const refusedByName = (results: PromiseSettledResult<any>[]) =>
95
+ results
96
+ .filter(one => one.status === 'rejected')
97
+ .forEach((one: any) => expect(NAMED).toContain(one.reason?.message))
98
+
99
+ it('two pool assigns at once: one waiting thread, in one of the two pools', async () => {
100
+ const endings: string[] = []
101
+
102
+ for (let round = 0; round < 20; round++) {
103
+ const instance = await aCase(`two-${round}`)
104
+
105
+ const results = await Promise.allSettled([db.transaction(toPool(instance, finance)), db.transaction(toPool(instance, support))])
106
+ refusedByName(results)
107
+
108
+ const threads = await threadsOf(instance)
109
+ const after = await reread(instance)
110
+ endings.push(`${results.filter(one => one.status === 'fulfilled').length} won`)
111
+
112
+ expect(threads.map((thread: any) => thread.state)).toEqual(['unassigned'])
113
+ expect([[finance.id], [support.id]]).toContainEqual(poolOf(after))
114
+ expect(after.threadsMin).toBe(1)
115
+ }
116
+
117
+ console.log('endings', [...new Set(endings)].join(' · '))
118
+ }, 120000)
119
+
120
+ it('a pool assign and a pick by someone outside the role at once: exactly one wins', async () => {
121
+ const endings: string[] = []
122
+
123
+ for (let round = 0; round < 20; round++) {
124
+ const instance = await aCase(`pick-${round}`)
125
+
126
+ const [assigned, picked] = await Promise.allSettled([
127
+ db.transaction(toPool(instance, finance)),
128
+ db.transaction((tx: any) => pick(instance.id, as(outsider)(tx)))
129
+ ])
130
+ refusedByName([assigned, picked])
131
+
132
+ const threads = await threadsOf(instance)
133
+ const after = await reread(instance)
134
+ endings.push(`assign ${assigned.status} · pick ${picked.status}`)
135
+
136
+ expect([assigned.status, picked.status].filter(status => status === 'fulfilled').length).toBe(1)
137
+
138
+ if (picked.status === 'fulfilled') {
139
+ expect(threads.map((thread: any) => [thread.state, thread.assigneeId])).toEqual([['assigned', outsider.id]])
140
+ expect(poolOf(after)).toEqual([])
141
+ } else {
142
+ expect(threads.map((thread: any) => thread.state)).toEqual(['unassigned'])
143
+ expect(poolOf(after)).toEqual([finance.id])
144
+ }
145
+ }
146
+
147
+ console.log('endings', [...new Set(endings)].join(' · '))
148
+ }, 120000)
149
+
150
+ it('moving a pool while a member of it claims the waiting thread: exactly one wins', async () => {
151
+ const endings: string[] = []
152
+
153
+ for (let round = 0; round < 20; round++) {
154
+ const instance = await aCase(`claim-${round}`)
155
+ await db.transaction(toPool(instance, finance))
156
+ const [waiting] = await threadsOf(instance)
157
+
158
+ const [moved, claimed] = await Promise.allSettled([
159
+ db.transaction(toPool(instance, support)),
160
+ db.transaction((tx: any) => start(waiting.id, {}, '', as(inFinance)(tx)))
161
+ ])
162
+ refusedByName([moved, claimed])
163
+
164
+ const threads = await threadsOf(instance)
165
+ const after = await reread(instance)
166
+ endings.push(`move ${moved.status} · claim ${claimed.status}`)
167
+
168
+ expect([moved.status, claimed.status].filter(status => status === 'fulfilled').length).toBe(1)
169
+ expect(threads.length).toBe(1)
170
+
171
+ if (claimed.status === 'fulfilled') {
172
+ expect([threads[0].state, threads[0].assigneeId]).toEqual(['started', inFinance.id])
173
+ expect(poolOf(after)).toEqual([finance.id])
174
+ } else {
175
+ expect([threads[0].state, threads[0].assigneeId || null]).toEqual(['unassigned', null])
176
+ expect(poolOf(after)).toEqual([support.id])
177
+ }
178
+ }
179
+
180
+ console.log('endings', [...new Set(endings)].join(' · '))
181
+ }, 120000)
182
+ })
@@ -154,18 +154,18 @@ describe('work door standing', () => {
154
154
  * door reaches nobody. One shared sentence would leave the reader with the wrong action.
155
155
  */
156
156
  it('says an unassigned door reaches nobody, not that it passes through', () => {
157
- const door = judgeDoor(assignment('작업 지시 배정', { installed: { assigneeRole: undefined } }))
157
+ const door = judgeDoor(assignment('작업 지시 배정', { installed: { assigneeRoles: [] } }))
158
158
 
159
159
  assert.equal(door.standing, 'off')
160
160
  assert.equal(door.reason, 'no-assignee')
161
161
  })
162
162
 
163
163
  it('reads a bound role as standing and names it', () => {
164
- const door = judgeDoor(assignment('정비 배정', { installed: { assigneeRole: 'MAINTENANCE-LEAD' } }))
164
+ const door = judgeDoor(assignment('정비 배정', { installed: { assigneeRoles: ['MAINTENANCE-LEAD', 'SHIFT-LEAD'] } }))
165
165
 
166
166
  assert.equal(door.standing, 'on')
167
167
  assert.equal(door.reason, 'assignee-bound')
168
- assert.equal(door.assigneeRole, 'MAINTENANCE-LEAD')
168
+ assert.deepEqual(door.assigneeRoles, ['MAINTENANCE-LEAD', 'SHIFT-LEAD'])
169
169
  })
170
170
 
171
171
  /** An approval line on an assignment door is not what fills it, and must not read as standing. */
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "this task ({id}) has already been terminated with the {state} status.",
39
39
  "error.activity-instance approval line is set": "this task already has its approval line; it is set on the task's detail screen.",
40
40
  "error.activity-instance assignee not in this domain": "these are not people of this site: {emails}",
41
+ "error.activity-instance a role is not an assignee": "a role cannot be an assignee - it would go to one person of the role. to give it to anyone of the role, set the assignee role.",
42
+ "error.activity-instance assign people or a role, not both": "assign it to people or to a role, not both at once.",
43
+ "error.activity-instance role not in this domain": "this role is not of this site: {role}",
44
+ "error.activity-instance assignee role named twice": "the same role is named more than once: {role}. name each role once.",
45
+ "error.activity-instance role has no members": "nobody holds the role {role}, so nobody would see this task. add people to the role first.",
41
46
  "error.activity-instance draft is gone": "this draft went out or was thrown away in the meantime. please read the list again.",
42
47
  "error.activity-instance not found": "this task ({activityInstance}) cannot be found.",
43
48
  "error.activity-instance not a draft any more": "this draft has already gone out, so it cannot be thrown away.",
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "esta tarea ({id}) ya finalizó con el estado {state}.",
39
39
  "error.activity-instance approval line is set": "esta tarea ya tiene su línea de aprobación; se configura en la pantalla de detalle de la tarea.",
40
40
  "error.activity-instance assignee not in this domain": "estas personas no pertenecen a este sitio: {emails}",
41
+ "error.activity-instance a role is not an assignee": "un rol no puede ser asignado: llegaría a una sola persona del rol. para dárselo a cualquiera del rol, indique el rol asignado.",
42
+ "error.activity-instance assign people or a role, not both": "asígnelo a personas o a un rol, no a ambos a la vez.",
43
+ "error.activity-instance role not in this domain": "este rol no pertenece a este sitio: {role}",
44
+ "error.activity-instance assignee role named twice": "el mismo rol aparece más de una vez: {role}. indique cada rol una sola vez.",
45
+ "error.activity-instance role has no members": "nadie tiene el rol {role}, así que nadie vería esta tarea. añada personas al rol primero.",
41
46
  "error.activity-instance draft is gone": "este borrador se envió o se descartó mientras tanto. vuelva a cargar la lista.",
42
47
  "error.activity-instance not found": "no se encuentra esta tarea ({activityInstance}).",
43
48
  "error.activity-instance not a draft any more": "este borrador ya se envió, así que no se puede descartar.",
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "このタスク({id})はすでに{state}状態で終了しています。",
39
39
  "error.activity-instance approval line is set": "この業務は決裁ラインが決まっています。決裁ラインは業務詳細で変更します。",
40
40
  "error.activity-instance assignee not in this domain": "このサイトの人ではありません: {emails}",
41
+ "error.activity-instance a role is not an assignee": "割当者に役割は指定できません。役割の一人にしか届きません。その役割の誰にでも任せるには割当役割を指定してください。",
42
+ "error.activity-instance assign people or a role, not both": "人か役割のどちらか一方に割り当ててください。",
43
+ "error.activity-instance role not in this domain": "このサイトの役割ではありません: {role}",
44
+ "error.activity-instance assignee role named twice": "同じ役割が複数回指定されています: {role}。役割はそれぞれ一度だけ指定してください。",
45
+ "error.activity-instance role has no members": "役割 {role} に人がいないため、誰もこの業務を見られません。先に役割に人を追加してください。",
41
46
  "error.activity-instance draft is gone": "この下書きはその間に発行されたか破棄されました。一覧を読み直してください。",
42
47
  "error.activity-instance not found": "このタスク({activityInstance})が見つかりません。",
43
48
  "error.activity-instance not a draft any more": "この下書きはすでに発行されたため、破棄できません。",
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "이 작업({id})는 이미 {state} 상태로 종료되었습니다.",
39
39
  "error.activity-instance approval line is set": "이 업무에는 결재선이 지정되어 있습니다. 업무 상세 화면에서 결재선을 변경해 주세요.",
40
40
  "error.activity-instance assignee not in this domain": "이 사업장 사람이 아닙니다: {emails}",
41
+ "error.activity-instance a role is not an assignee": "피할당자에는 역할을 넣을 수 없습니다. 역할 중 한 사람에게만 갑니다. 그 역할의 누구에게나 맡기려면 피할당 역할을 지정해 주세요.",
42
+ "error.activity-instance assign people or a role, not both": "사람과 역할 중 하나에만 할당할 수 있습니다.",
43
+ "error.activity-instance role not in this domain": "이 사업장의 역할이 아닙니다: {role}",
44
+ "error.activity-instance assignee role named twice": "같은 역할을 두 번 이상 넣었습니다: {role}. 역할마다 한 번씩만 넣어 주세요.",
45
+ "error.activity-instance role has no members": "{role} 역할에 사람이 없어 아무도 이 업무를 볼 수 없습니다. 먼저 역할에 사람을 넣어 주세요.",
41
46
  "error.activity-instance draft is gone": "이 초안은 그사이 발행되었거나 버려졌습니다. 목록을 새로 읽어 주십시오.",
42
47
  "error.activity-instance not found": "이 작업({activityInstance})을 찾을 수 없습니다.",
43
48
  "error.activity-instance not a draft any more": "이 초안은 이미 발행되어 버릴 수 없습니다.",
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "Tugas ini ({id}) telah tamat dengan status {state}.",
39
39
  "error.activity-instance approval line is set": "tugas ini sudah mempunyai laluan kelulusan; ia ditetapkan pada skrin butiran tugas.",
40
40
  "error.activity-instance assignee not in this domain": "ini bukan orang dalam domain ini: {emails}",
41
+ "error.activity-instance a role is not an assignee": "peranan tidak boleh menjadi penerima tugasan - ia akan pergi kepada seorang sahaja daripada peranan itu. untuk memberikannya kepada sesiapa dalam peranan itu, tetapkan peranan penerima.",
42
+ "error.activity-instance assign people or a role, not both": "tugaskan kepada orang atau kepada peranan, bukan kedua-duanya sekali.",
43
+ "error.activity-instance role not in this domain": "peranan ini bukan dari domain ini: {role}",
44
+ "error.activity-instance assignee role named twice": "peranan yang sama dinamakan lebih daripada sekali: {role}. namakan setiap peranan sekali sahaja.",
45
+ "error.activity-instance role has no members": "tiada sesiapa memegang peranan {role}, jadi tiada sesiapa akan melihat tugas ini. tambah orang ke peranan itu dahulu.",
41
46
  "error.activity-instance draft is gone": "draf ini telah dikeluarkan atau dibuang sementara itu. sila baca senarai semula.",
42
47
  "error.activity-instance not found": "Tugas ini ({activityInstance}) tidak dijumpai.",
43
48
  "error.activity-instance not a draft any more": "draf ini sudah dikeluarkan, jadi ia tidak boleh dibuang.",
@@ -38,6 +38,11 @@
38
38
  "error.activity-instance is already terminated": "此任务({id})已以{state}状态终止。",
39
39
  "error.activity-instance approval line is set": "此业务已设定审批线,请在业务详情中修改。",
40
40
  "error.activity-instance assignee not in this domain": "以下不是本站点的人员:{emails}",
41
+ "error.activity-instance a role is not an assignee": "角色不能作为被分配人——只会分给该角色中的一个人。要交给该角色的任何人,请指定被分配角色。",
42
+ "error.activity-instance assign people or a role, not both": "只能分配给人员或角色之一,不能同时分配。",
43
+ "error.activity-instance role not in this domain": "此角色不属于本站点:{role}",
44
+ "error.activity-instance assignee role named twice": "同一角色被指定了多次:{role}。每个角色只能指定一次。",
45
+ "error.activity-instance role has no members": "角色 {role} 中没有人员,没有人能看到此任务。请先为该角色添加人员。",
41
46
  "error.activity-instance draft is gone": "此草稿在此期间已发布或已丢弃,请重新读取列表。",
42
47
  "error.activity-instance not found": "未找到此任务({activityInstance})。",
43
48
  "error.activity-instance not a draft any more": "此草稿已发布,无法丢弃。",