@things-factory/worklist 10.1.261 → 10.1.262

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/worklist",
3
- "version": "10.1.261",
3
+ "version": "10.1.262",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "exports": {
@@ -57,16 +57,16 @@
57
57
  "@operato/p13n": "^10.29.43",
58
58
  "@operato/popup": "^10.29.43",
59
59
  "@operato/shell": "^10.29.69",
60
- "@things-factory/attachment-base": "^10.1.261",
61
- "@things-factory/auth-base": "^10.1.261",
62
- "@things-factory/board-service": "^10.1.261",
63
- "@things-factory/context-ui": "^10.1.261",
64
- "@things-factory/i18n-base": "^10.1.261",
65
- "@things-factory/notification": "^10.1.261",
66
- "@things-factory/organization": "^10.1.261",
67
- "@things-factory/personalization": "^10.1.261",
68
- "@things-factory/scheduler-client": "^10.1.261",
69
- "@things-factory/shell": "^10.1.261"
60
+ "@things-factory/attachment-base": "^10.1.262",
61
+ "@things-factory/auth-base": "^10.1.262",
62
+ "@things-factory/board-service": "^10.1.262",
63
+ "@things-factory/context-ui": "^10.1.262",
64
+ "@things-factory/i18n-base": "^10.1.262",
65
+ "@things-factory/notification": "^10.1.262",
66
+ "@things-factory/organization": "^10.1.262",
67
+ "@things-factory/personalization": "^10.1.262",
68
+ "@things-factory/scheduler-client": "^10.1.262",
69
+ "@things-factory/shell": "^10.1.262"
70
70
  },
71
- "gitHead": "06537757f8708e6a511c6232e8792f18fdd6a986"
71
+ "gitHead": "2d5babff1e0f83bb0dfdf2ec91e4e7c00f9ac5bd"
72
72
  }
@@ -0,0 +1,75 @@
1
+ import { join } from 'path'
2
+
3
+ /**
4
+ * handOut - a to-do of a module's own handed to one person (2026-11-08). It has no creator, so it is the person's 할 일
5
+ * and nobody's 상신함 - the manager who hands a course to themselves included. Issued as its own assignee before, a
6
+ * course to take landed in the learner's 상신함. Real entities on sqlite; 할 일 and 상신함 are read by their own rules.
7
+ */
8
+
9
+ const { createSqliteTestDataSource } = require(join(__dirname, '..', '..', 'ops-master', 'test', 'support', 'database.cjs'))
10
+ const DIST = join(__dirname, '..', 'dist-server')
11
+ const { Activity } = require(join(DIST, 'service', 'activity', 'activity.js'))
12
+ const { ActivityInstance } = require(join(DIST, 'service', 'activity-instance', 'activity-instance.js'))
13
+ const { ActivityInstanceHistory } = require(join(DIST, 'service', 'activity-instance', 'activity-instance-history.js'))
14
+ const { ActivityInstanceHistoryEntitySubscriber } = require(join(DIST, 'service', 'activity-instance', 'event-subscriber.js'))
15
+ const { ActivityThread } = require(join(DIST, 'service', 'activity-thread', 'activity-thread.js'))
16
+ const { ActivityApproval } = require(join(DIST, 'service', 'activity-approval', 'activity-approval.js'))
17
+ const { myOpenThreadsWhere } = require(join(DIST, 'service', 'activity-thread', 'my-open-threads.js'))
18
+ const { handOut } = require(join(DIST, 'controllers', 'activity-instance', 'hand-out.js'))
19
+ const { Domain } = require('@things-factory/shell')
20
+ const { User } = require('@things-factory/auth-base')
21
+
22
+ let db: any
23
+ let here: any
24
+ let manager: any
25
+ let learner: any
26
+ let activity: any
27
+
28
+ beforeAll(async () => {
29
+ db = createSqliteTestDataSource([Activity, ActivityInstance, ActivityInstanceHistory, ActivityThread, ActivityApproval], {
30
+ subscribers: [ActivityInstanceHistoryEntitySubscriber]
31
+ })
32
+ await db.initialize()
33
+ here = await db.getRepository(Domain).save({ name: 'here', subdomain: 'here' })
34
+ const person = (name: string) => db.getRepository(User).save({ name, email: `${name}@example.com`, password: 'x', status: 'activated', userType: 'user', domains: [here] })
35
+ manager = await person('manager')
36
+ learner = await person('learner')
37
+ activity = await db.getRepository(Activity).save({ domain: here, name: 'Learning Course', activityType: 'standard', startingType: 'issue' })
38
+ })
39
+
40
+ afterAll(async () => db?.destroy())
41
+
42
+ const as = (user: any, tx: any) => ({ state: { domain: here, user, tx }, t: (key: string) => key }) as any
43
+
44
+ /** The cases in a person's 할 일, by the rule the list, the calendar and the badge read. */
45
+ async function todoOf(user: any): Promise<string[]> {
46
+ const rows = await db
47
+ .getRepository(ActivityThread)
48
+ .createQueryBuilder('at')
49
+ .innerJoin('at.activityInstance', 'ai')
50
+ .where(myOpenThreadsWhere({ userId: user.id, roles: [] }))
51
+ .select('ai.id', 'id')
52
+ .getRawMany()
53
+ return rows.map((one: any) => one.id)
54
+ }
55
+
56
+ /** The cases in a person's 상신함 - what they put up (activity-instance-query: `ai.creator = :user`). */
57
+ async function requestsOf(user: any): Promise<string[]> {
58
+ return (await db.getRepository(ActivityInstance).createQueryBuilder('ai').where('ai.creator = :user', { user: user.id }).getMany()).map((one: any) => one.id)
59
+ }
60
+
61
+ test('★ a to-do handed to someone is in their 할 일 and in nobody\'s 상신함', async () => {
62
+ const instance = await db.transaction((tx: any) => handOut({ activityId: activity.id, name: '보안 교육 수강', assignee: learner }, as(manager, tx)))
63
+ const saved = await db.getRepository(ActivityInstance).findOne({ where: { id: instance.id }, relations: ['creator', 'issuer'] })
64
+ expect(saved.creator).toBeNull()
65
+ expect(saved.issuer?.id).toBe(manager.id)
66
+ expect(await todoOf(learner)).toContain(instance.id)
67
+ expect(await requestsOf(learner)).not.toContain(instance.id)
68
+ expect(await requestsOf(manager)).not.toContain(instance.id)
69
+ })
70
+
71
+ test('★ handed by a manager to themselves, it is still their 할 일 - not their 상신함', async () => {
72
+ const instance = await db.transaction((tx: any) => handOut({ activityId: activity.id, name: '보안 교육 수강', assignee: manager }, as(manager, tx)))
73
+ expect(await todoOf(manager)).toContain(instance.id)
74
+ expect(await requestsOf(manager)).not.toContain(instance.id)
75
+ })