@things-factory/worklist 6.0.43 → 6.0.46
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/client/bootstrap.ts +5 -0
- package/client/components/activity-starter-form.ts +52 -303
- package/client/pages/activity/activity-list-page.ts +44 -28
- package/client/pages/activity/activity-page.ts +3 -3
- package/client/pages/activity/activity-partial-view.ts +2 -1
- package/client/pages/activity/starter-list-page.ts +16 -11
- package/client/pages/activity-instance/activity-instance-search-page.ts +2 -19
- package/client/pages/activity-instance/activity-instance-start-page.ts +514 -0
- package/client/pages/activity-stats/activity-stats-importer.ts +97 -0
- package/client/pages/activity-stats/activity-stats-list-page.ts +348 -0
- package/client/pages/activity-thread/activity-thread-page.ts +1 -1
- package/client/pages/installable-activity/installable-activity-list-page.ts +7 -5
- package/client/pages/todo/approval-done-list-page.ts +340 -0
- package/client/pages/todo/approval-pending-list-page.ts +2 -2
- package/client/pages/todo/done-list-calendar-page.ts +115 -0
- package/client/pages/todo/done-list-page.ts +2 -3
- package/client/pages/todo/draft-list-page.ts +26 -102
- package/client/pages/todo/pickable-list-page.ts +2 -1
- package/client/pages/todo/todo-list-page.ts +1 -1
- package/client/route.ts +14 -2
- package/client/templates/activity-approval-context-template.ts +4 -0
- package/client/templates/activity-instance-context-template.ts +171 -0
- package/client/templates/activity-thread-context-template.ts +4 -0
- package/client/themes/calendar-theme.css +54 -0
- package/client/types/activity-instance-type.ts +4 -2
- package/client/types/activity-instance.ts +2 -2
- package/client/types/activity.ts +7 -0
- package/client/types/types.ts +8 -0
- package/dist-client/bootstrap.d.ts +1 -0
- package/dist-client/bootstrap.js +5 -0
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/activity-starter-form.d.ts +2 -5
- package/dist-client/components/activity-starter-form.js +54 -247
- package/dist-client/components/activity-starter-form.js.map +1 -1
- package/dist-client/pages/activity/activity-list-page.d.ts +1 -1
- package/dist-client/pages/activity/activity-list-page.js +45 -30
- package/dist-client/pages/activity/activity-list-page.js.map +1 -1
- package/dist-client/pages/activity/activity-page.d.ts +1 -1
- package/dist-client/pages/activity/activity-page.js +3 -3
- package/dist-client/pages/activity/activity-page.js.map +1 -1
- package/dist-client/pages/activity/activity-partial-view.js +2 -2
- package/dist-client/pages/activity/activity-partial-view.js.map +1 -1
- package/dist-client/pages/activity/starter-list-page.d.ts +1 -0
- package/dist-client/pages/activity/starter-list-page.js +14 -11
- package/dist-client/pages/activity/starter-list-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-page.d.ts +2 -2
- package/dist-client/pages/activity-instance/activity-instance-page.js +19 -10
- package/dist-client/pages/activity-instance/activity-instance-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-search-page.js +1 -8
- package/dist-client/pages/activity-instance/activity-instance-search-page.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +49 -0
- package/dist-client/pages/activity-instance/activity-instance-start-page.js +450 -0
- package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -0
- package/dist-client/pages/activity-stats/activity-stats-importer.d.ts +22 -0
- package/dist-client/pages/activity-stats/activity-stats-importer.js +100 -0
- package/dist-client/pages/activity-stats/activity-stats-importer.js.map +1 -0
- package/dist-client/pages/activity-stats/activity-stats-list-page.d.ts +62 -0
- package/dist-client/pages/activity-stats/activity-stats-list-page.js +326 -0
- package/dist-client/pages/activity-stats/activity-stats-list-page.js.map +1 -0
- package/dist-client/pages/activity-thread/activity-thread-page.js +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/pages/installable-activity/installable-activity-list-page.js +7 -5
- package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-done-list-page.d.ts +39 -0
- package/dist-client/pages/todo/approval-done-list-page.js +338 -0
- package/dist-client/pages/todo/approval-done-list-page.js.map +1 -0
- package/dist-client/pages/todo/approval-pending-list-page.js +2 -2
- package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-calendar-page.d.ts +24 -0
- package/dist-client/pages/todo/done-list-calendar-page.js +107 -0
- package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -0
- package/dist-client/pages/todo/done-list-page.js +2 -3
- package/dist-client/pages/todo/done-list-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +1 -0
- package/dist-client/pages/todo/draft-list-page.js +25 -99
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/pages/todo/pickable-list-page.d.ts +1 -0
- package/dist-client/pages/todo/pickable-list-page.js +2 -1
- package/dist-client/pages/todo/pickable-list-page.js.map +1 -1
- package/dist-client/pages/todo/todo-list-page.js +1 -1
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +11 -2
- package/dist-client/route.js.map +1 -1
- package/dist-client/templates/activity-approval-context-template.js +4 -0
- package/dist-client/templates/activity-approval-context-template.js.map +1 -1
- package/dist-client/templates/activity-instance-context-template.d.ts +2 -0
- package/dist-client/templates/activity-instance-context-template.js +145 -0
- package/dist-client/templates/activity-instance-context-template.js.map +1 -0
- package/dist-client/templates/activity-thread-context-template.js +4 -0
- package/dist-client/templates/activity-thread-context-template.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/types/activity-instance-type.d.ts +3 -2
- package/dist-client/types/activity-instance-type.js +2 -2
- package/dist-client/types/activity-instance-type.js.map +1 -1
- package/dist-client/types/activity-instance.d.ts +1 -1
- package/dist-client/types/activity-instance.js +2 -2
- package/dist-client/types/activity-instance.js.map +1 -1
- package/dist-client/types/activity.d.ts +5 -0
- package/dist-client/types/activity.js +5 -0
- package/dist-client/types/activity.js.map +1 -1
- package/dist-client/types/types.d.ts +4 -0
- package/dist-client/types/types.js +6 -0
- package/dist-client/types/types.js.map +1 -1
- package/dist-server/controllers/activity-instance/assign.js +1 -1
- package/dist-server/controllers/activity-instance/assign.js.map +1 -1
- package/dist-server/controllers/activity-instance/draft.js +24 -6
- package/dist-server/controllers/activity-instance/draft.js.map +1 -1
- package/dist-server/controllers/activity-instance/index.js +1 -1
- package/dist-server/controllers/activity-instance/index.js.map +1 -1
- package/dist-server/controllers/activity-instance/issue.js +105 -0
- package/dist-server/controllers/activity-instance/issue.js.map +1 -0
- package/dist-server/controllers/activity-instance/pick.js +1 -1
- package/dist-server/controllers/activity-instance/pick.js.map +1 -1
- package/dist-server/controllers/activity-instance/post.js +7 -7
- package/dist-server/controllers/activity-instance/post.js.map +1 -1
- package/dist-server/controllers/common.js +33 -9
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/routes.js +2 -2
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/activity/activity-history.js +6 -2
- package/dist-server/service/activity/activity-history.js.map +1 -1
- package/dist-server/service/activity/activity-query.js +84 -1
- package/dist-server/service/activity/activity-query.js.map +1 -1
- package/dist-server/service/activity/activity-type.js +8 -0
- package/dist-server/service/activity/activity-type.js.map +1 -1
- package/dist-server/service/activity/activity.js +36 -3
- package/dist-server/service/activity/activity.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-query.js +48 -0
- package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-history.js +1 -1
- package/dist-server/service/activity-instance/activity-instance-history.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-mutation.js +6 -6
- package/dist-server/service/activity-instance/activity-instance-mutation.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +2 -2
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-type.js +62 -50
- package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance.js +4 -23
- package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
- package/dist-server/service/activity-stats/activity-stats-query.js +93 -0
- package/dist-server/service/activity-stats/activity-stats-query.js.map +1 -0
- package/dist-server/service/activity-stats/activity-stats-type.js +47 -0
- package/dist-server/service/activity-stats/activity-stats-type.js.map +1 -0
- package/dist-server/service/activity-stats/index.js +6 -0
- package/dist-server/service/activity-stats/index.js.map +1 -0
- package/dist-server/service/activity-summary/activity-summary-query.js +5 -23
- package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
- package/dist-server/service/index.js +2 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/installable-activity/installable-activity.js +4 -0
- package/dist-server/service/installable-activity/installable-activity.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/worklist/activity-bank.md +22 -0
- package/helps/worklist/{activity-approval.md → activity-stats.md} +1 -1
- package/helps/worklist/activity.md +91 -0
- package/helps/worklist/draft-list.md +19 -0
- package/helps/worklist/starter-list.md +34 -0
- package/helps/worklist/worklist-concept.md +11 -8
- package/package.json +3 -2
- package/server/controllers/activity-instance/assign.ts +1 -1
- package/server/controllers/activity-instance/draft.ts +33 -6
- package/server/controllers/activity-instance/index.ts +1 -1
- package/server/controllers/activity-instance/issue.ts +175 -0
- package/server/controllers/activity-instance/pick.ts +1 -1
- package/server/controllers/common.ts +43 -9
- package/server/routes.ts +2 -2
- package/server/service/activity/activity-history.ts +5 -2
- package/server/service/activity/activity-query.ts +85 -2
- package/server/service/activity/activity-type.ts +15 -2
- package/server/service/activity/activity.ts +28 -2
- package/server/service/activity-approval/activity-approval-query.ts +45 -1
- package/server/service/activity-instance/activity-instance-history.ts +1 -1
- package/server/service/activity-instance/activity-instance-mutation.ts +7 -7
- package/server/service/activity-instance/activity-instance-query.ts +3 -3
- package/server/service/activity-instance/activity-instance-type.ts +13 -4
- package/server/service/activity-instance/activity-instance.ts +4 -16
- package/server/service/activity-stats/activity-stats-query.ts +94 -0
- package/server/service/activity-stats/activity-stats-type.ts +34 -0
- package/server/service/activity-stats/index.ts +3 -0
- package/server/service/activity-summary/activity-summary-query.ts +5 -23
- package/server/service/index.ts +2 -0
- package/server/service/installable-activity/installable-activity.ts +4 -1
- package/things-factory.config.js +5 -2
- package/translations/en.json +23 -0
- package/translations/ko.json +29 -6
- package/translations/ms.json +23 -0
- package/translations/zh.json +23 -0
- package/client/pages/activity-instance/activity-instance-page.ts +0 -445
- package/server/controllers/activity-instance/post.ts +0 -140
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 업무 뱅크
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
|
|
5
|
+
워크리스트 시스템에서 미할당 업무들을 모아둔 곳인 업무뱅크는, 다양한 업무들을 포함하는 일종의 업무 목록 혹은 대기열(queue)입니다. 이 업무들은 일반적으로 프로젝트나 팀에서 진행해야 할 일들 중 미해결된 업무들로 구성됩니다. 업무뱅크에 포함된 업무들은 우선순위, 난이도, 기간 등 다양한 정보들을 가지고 있으며, 해당 업무를 담당하는 사용자가 할당되기 전까지는 "미할당 상태"로 존재합니다.
|
|
6
|
+
|
|
7
|
+
업무뱅크에서 업무를 선택(pick)하면, 해당 업무를 수행할 수 있는 자격 역할을 가진 사용자가 그 업무를 자신의 TODO 리스트로 옮길 수 있습니다. 이렇게 옮겨진 업무는 해당 사용자의 개인 TODO 리스트에 추가되어, 이후 해당 사용자가 해당 업무를 수행하도록 할당됩니다.
|
|
8
|
+
|
|
9
|
+
이러한 시스템을 통해, 업무뱅크를 통해 미할당된 업무들을 한 곳에서 모아서 효율적으로 관리할 수 있습니다. 또한, 업무를 수행하는 사용자들이 자신의 업무 선택을 할 수 있는 기능을 제공하여, 업무를 더욱 효과적으로 분배하고 업무 수행의 효율성을 높일 수 있습니다.
|
|
10
|
+
|
|
11
|
+
## 업무 쇼핑
|
|
12
|
+
|
|
13
|
+
아직 할당되지 않은 작업들의 리스트를 조회하고, 그 중에서 사용자가 스스로에게 해당 업무를 할당하여 수행할 수 있는 기능입니다.
|
|
14
|
+
미할당 업무를 스스로에게 할당하는 것을 업무를 선택(PICK)한다고 하며, 이런 대상업무들이 업무뱅크에 리스트되어 있습니다.
|
|
15
|
+
|
|
16
|
+
사용자가 업무뱅크에서 볼 수 있는 미할당 업무들은 사용자에게 할당되지는 않았지만, 해당 업무에 대해서 사용자가 수행할 수 있는 자격이 있는 업무들만 조회되게 됩니다.
|
|
17
|
+
그러한 자격은 보통 시스템에서 부여된 역할(Role)에 의해서 결정됩니다.
|
|
18
|
+
|
|
19
|
+
보통 업무를 정의하고 업무뱅크에 올릴 때(POST) 해당 업무를 수행할 수 있는 자격 역할(Role)을 지정하게 됩니다.
|
|
20
|
+
따라서, 해당 역할(Role)을 가진 사용자들이 그 업무를 선택(PICK)할 수 있는 것입니다.
|
|
21
|
+
|
|
22
|
+
사용자가 선택(PICK)한 업무는 나의 할일 리스트에 포함되게 되며, 업무뱅크 리스트에서 사라지게 됩니다.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# 업무정의(Activity)
|
|
2
|
+
|
|
3
|
+
Activity는 "업무정의" 라고 이해할 수 있다.
|
|
4
|
+
|
|
5
|
+
워크리스트 시스템에서는 업무의 인스턴스를 생성하고 수행, 검토, 결재 승인, 완료 까지의 업무인스턴스의 라이프사이클을 관리하며, 사용자와 인터렉션을 통해서 업무 수행의 효율을 높이는 시스템이다.
|
|
6
|
+
이 업무 인스턴스의 모델이 되는 것을 "Activity"라고 한다.
|
|
7
|
+
|
|
8
|
+
## 워크리스트 내부 엔티티 구조
|
|
9
|
+
|
|
10
|
+
- 업무정의 : Activity
|
|
11
|
+
- 업무인스턴스 : Activity Instance
|
|
12
|
+
- 업무쓰레드 : Activity Thread - 하나의 업무인스턴스는 여러 피할당자에 의해서 수행될 수 있는데, 각각의 피할당자의 업무 진행과정을 관리하는 엔티티이다.
|
|
13
|
+
- 승인 이력 : Activity Approval - 업무 쓰레드에 대한 각각의 승인과정을 관리하는 엔티티이다.
|
|
14
|
+
|
|
15
|
+
## 업무정의의 속성
|
|
16
|
+
|
|
17
|
+
- 이름 : 업무정의의 이름이며, 해당 업무정의로 생성된 업무인스턴스들의 디폴트 이름으로 제시된다.
|
|
18
|
+
- 설명 : 업무정의에 대한 설명이며, 해당 업무정의로 생성된 업무인스턴스들의 디폴트 설명으로 제시된다.
|
|
19
|
+
- 상태
|
|
20
|
+
- 초안작업중 : 업무정의를 작성중이며 배포되기 전이다. 업무인스턴스를 생성할 수 없는 상태이다.
|
|
21
|
+
- 배포됨 : 업무정의가 완료되어 배포된 상태이다.
|
|
22
|
+
- 폐기 : 업무정의가 더 이상 사용되지 않고 폐기되었다.
|
|
23
|
+
- 업무타입
|
|
24
|
+
- BPMN 2.0 명세에 의한 태스크 타입이다.
|
|
25
|
+
- 사용자가 수행하는 업무는 'User' 태스크 타입을 지정한다.
|
|
26
|
+
- 시작 유형
|
|
27
|
+
- [새업무 시작](./starter-list.md)의 시작업무 유형을 참고한다.
|
|
28
|
+
- 다중인스턴스 유형
|
|
29
|
+
- 하나의 업무인스턴스의 피할당자를 한명만 할 것인지, 여러명을 할 것인지를 지정하며, 여러명인 경우 동시에 수행할지, 순차적으로 수행할지를 지정한다.
|
|
30
|
+
- parallel : 여러 할당자가 동시에 하나의 업무인스턴스를 수행하는 경우
|
|
31
|
+
- sequential : 여러 할당자가 순처적으로 하나의 업무인스턴스를 수행하는 경우
|
|
32
|
+
- 설정하지 않으면, 단일 피할당자에 의해서만 수행됨을 의미한다.
|
|
33
|
+
- 검색 키
|
|
34
|
+
- 업무인스턴스 이력에서 데이터를 기반으로 검색할 수 있도록, input 데이타들 중에서 5개까지 검색키로 지정할 수 있다.
|
|
35
|
+
- 해당 업무정의의 업무인스턴스 중에서 내가 수행한 업무들은 '업무수행이력' 메뉴에서 검색해볼 수 있는데, '업무수행이력'의 하위메뉴 중에서 업무정의의 이름과 동일한 메뉴에서 검색해볼 수 있다.
|
|
36
|
+
- 검색 키로 지정된 input 데이타는 이 메뉴에서 검색키로 활용된다.
|
|
37
|
+
- 우선순위
|
|
38
|
+
- 업무인스턴스의 디폴트 우선순위로 제시된다.
|
|
39
|
+
- 스케쥴
|
|
40
|
+
- 업무정의는 스케쥴에 의해서 인스턴스가 자동 생성될 수 있다. 여기서는 자동생성을 위한 스케쥴을 설정할 수 있다.
|
|
41
|
+
- 타임존
|
|
42
|
+
- 스케쥴 설정의 타임존을 설정한다.
|
|
43
|
+
- 미리보기
|
|
44
|
+
- 업무정의를 상징하는 이미지를 설정할 수 있다. 특히 모바일 환경에서 카드형식의 리스트에서 각 업무들을 식별하는데 효과적이다.
|
|
45
|
+
- 발급자 역할
|
|
46
|
+
- 사용자의 [시작가능한 업무]('./start-list.md')에 리스트될 수 있기 위해서는 발급자 역할을 가진 사용자 이어야 한다.
|
|
47
|
+
- 이 업무정의로 부터 업무 인스턴스를 생성할 수 있는 역할군을 지정한다.
|
|
48
|
+
- 피할당 역할
|
|
49
|
+
- 이 업무정의의 인스턴스의 피할당자가 될 수 있는 역할 군을 지정한다.
|
|
50
|
+
- [업무뱅크](./activity-bank.md)에 게시하는 경우, 해당 역할을 가진 사람만이 PICK할 수 있다.
|
|
51
|
+
- 관리자 역할
|
|
52
|
+
- 이 업무정의의 관리자 역할 군을 지정한다.
|
|
53
|
+
- 관리자는 이 업무정의의 모든 인스턴스의 현황과 이력을 조회할 수 있다.
|
|
54
|
+
- 피할당자들(assignees)
|
|
55
|
+
- 업무인스턴스의 디폴트 피할당자들을 조직 체계 내에서 지정할 수 있다.
|
|
56
|
+
- 이 피할당자들은 이 업무정의의 인스턴스가 issue될 때 자동으로 피할당된다.
|
|
57
|
+
- 결재선(approval line)
|
|
58
|
+
- 피할당자에 의해서 업무쓰레드가 수행되어 제출(submit)되면, 해당 결재선을 타고 승인의 과정을 거치게 된다.
|
|
59
|
+
- 화면타입
|
|
60
|
+
- 업무생성 및 수행과정에 시스템에 의해서 작성자에게 보여지게될 작업 화면의 유형
|
|
61
|
+
- Generated : 업무정의 모델에 의해서 동적으로 자동 생성된다.
|
|
62
|
+
- Template :
|
|
63
|
+
- Board : 화면 소스에 설정한 보드가 보여진다.
|
|
64
|
+
- CustomElement : 데이타 인터렉션 규약을 만족하는 커스텀 엘리먼트가 보여진다. 해당 커스텀엘리먼트는 in/out data를 입력으로 받고, in/out이 수정될 때 이벤트를 발생시키는 규약을 만족하여야 한다.
|
|
65
|
+
- Page : 브라우저의 페이지 라우팅을 지정할 수 있다.
|
|
66
|
+
- External URL : 외부 URL을 지정할 수 있다.
|
|
67
|
+
- 화면소스
|
|
68
|
+
- 화면타입에 해당하는 상세 설정을 한다.
|
|
69
|
+
- 뷰타입
|
|
70
|
+
- 업무수행과정 또는 이력을 조회할 때 보여지게될 작업 화면의 유형
|
|
71
|
+
- Generated : 업무정의 모델에 의해서 동적으로 자동 생성된다.
|
|
72
|
+
- Template :
|
|
73
|
+
- Board : 화면 소스에 설정한 보드가 보여진다.
|
|
74
|
+
- CustomElement : 데이타 인터렉션 규약을 만족하는 커스텀 엘리먼트가 보여진다. 해당 커스텀엘리먼트는 in/out data를 입력으로 받고, in/out이 수정될 때 이벤트를 발생시키는 규약을 만족하여야 한다.
|
|
75
|
+
- Page : 브라우저의 페이지 라우팅을 지정할 수 있다.
|
|
76
|
+
- External URL : 외부 URL을 지정할 수 있다.
|
|
77
|
+
- 뷰소스
|
|
78
|
+
- 뷰타입에 해당하는 상세 설정을 한다.
|
|
79
|
+
- 리포트타입
|
|
80
|
+
- 업무정의와 관련된 리포트를 제공할 때 보여지게될 작업 화면의 유형
|
|
81
|
+
- Generated : 업무정의 모델에 의해서 동적으로 자동 생성된다.
|
|
82
|
+
- Template :
|
|
83
|
+
- Board : 화면 소스에 설정한 보드가 보여진다.
|
|
84
|
+
- CustomElement : 데이타 인터렉션 규약을 만족하는 커스텀 엘리먼트가 보여진다. 해당 커스텀엘리먼트는 in/out data를 입력으로 받고, in/out이 수정될 때 이벤트를 발생시키는 규약을 만족하여야 한다.
|
|
85
|
+
- Page : 브라우저의 페이지 라우팅을 지정할 수 있다.
|
|
86
|
+
- External URL : 외부 URL을 지정할 수 있다.
|
|
87
|
+
- 리포트소스
|
|
88
|
+
- 리포트타입에 해당하는 상세 설정을 한다.
|
|
89
|
+
- 표준시간(ST)
|
|
90
|
+
- 이 업무정의로 만들어지는 업무인스턴스의 표준 수행시간을 의미한다.
|
|
91
|
+
- 이 업무정의로 만들어지는 업무인스턴스의 만기시간을 계산하기위해 설정된다.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 작성중인 업무
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
|
|
5
|
+
워크리스트 시스템에서 작성중인 업무는 일반적으로 "Draft" 상태로 분류됩니다. 이러한 업무는 아직 완료되지 않았거나, 작업이 일시 중단된 상태이며, 업무를 작성하고 있는 사용자가 해당 업무를 다시 가져와서 작업을 계속할 수 있도록 보관되어야 하는 상태입니다.
|
|
6
|
+
|
|
7
|
+
따라서, 워크리스트 시스템에서는 해당 사용자가 작성중인 업무를 리스팅할 수 있는 기능을 제공합니다. 이를 통해, 작성중인 업무를 쉽게 찾을 수 있으며, 다시 해당 업무를 가져와서 작업을 이어나갈 수 있습니다. 일반적으로, 작성중인 업무를 리스팅하는 기능은 사용자의 개인적인 작업 대시보드에서 제공되며, 해당 사용자가 작성 중인 모든 업무들의 요약 정보를 한 눈에 볼 수 있도록 구성되어 있습니다.
|
|
8
|
+
|
|
9
|
+
또한, 해당 기능은 작성중인 업무들의 상세 정보를 확인할 수 있는 링크를 제공하여, 사용자가 해당 업무의 내용을 다시 확인하거나 수정할 수 있도록 합니다. 이러한 기능을 통해, 작성중인 업무들을 보다 쉽게 관리하고, 업무 작성에 대한 효율성을 높일 수 있습니다.
|
|
10
|
+
|
|
11
|
+
### 작성중인 업무의 2가지 유형
|
|
12
|
+
|
|
13
|
+
[새업무 시작하기](./starter-list.md)에서 작성중인 업무의 2가지 유형에 대해서 참고하시기 바랍니다.
|
|
14
|
+
|
|
15
|
+
## 작동 방식
|
|
16
|
+
|
|
17
|
+
"작성중인 업무"는 업무를 정의하고 할당하고자 하는 사용자가 업무를 기획하는 과정에서 초안작업(Draft) 중인 상태의 업무를 의미합니다.
|
|
18
|
+
따라서, 이 상태의 업무는 아직 포스팅되기 전이며, 사용자가 그 과정에서 취소할 수도 있으며, 최종 완성하여 업무를 할당하거나 업무뱅크에 리스팅할 수도 있습니다.
|
|
19
|
+
이렇게 작성 완료되어 할당 또는 업무뱅크에 리스팅된 상태를 이슈된(Issued) 상태라고 합니다.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 새업무 시작하기
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
|
|
5
|
+
### 시작 가능 업무 (startable)
|
|
6
|
+
|
|
7
|
+
업무정의리스트에 정의된 업무들 중에서, 사용자가 임의로 시작할 수 있는 업무를 '시작 가능(startable)' 업무라고 합니다.
|
|
8
|
+
|
|
9
|
+
업무를 선택하여 제목과 설명을 입력하고 '초안 저장'을 클릭하면, 새로운 업무가 생성되고 상세한 내용을 작성할 수 있도록 해당 업무화면으로 열립니다.
|
|
10
|
+
그 업무는 [작성중인 업무](./draft-list.md)에 리스트되며, 언제든지 다시 열어서 편집할 수 있습니다.
|
|
11
|
+
|
|
12
|
+
### 시작 유형 (starting type)
|
|
13
|
+
|
|
14
|
+
시작 가능 업무는 두가지 유형으로 나뉩니다.
|
|
15
|
+
|
|
16
|
+
- 업무 할당 (issue) 유형
|
|
17
|
+
|
|
18
|
+
'업무 할당' 유형의 업무는 누군가(assignees)에게 업무를 할당하기 위해서 시작하는 업무입니다.
|
|
19
|
+
업무를 할당하기 위해서는 업무에 대한 설명과 주요 입력값을 업무를 수행할 피할당자(assignees)에게 제공해주어야 합니다.
|
|
20
|
+
이렇게 업무할당을 위해서 업무에 대한 설명과 입력값을 작성하는 작업을 위한 시작 유형이 '업무 할당(issue)' 입니다.
|
|
21
|
+
|
|
22
|
+
이 업무 작성이 완료되어 '업무 할당(issue)'을 하게되면, 피할당자의 '나의 할일'리스트에 해당업무가 할당되게 됩니다.
|
|
23
|
+
|
|
24
|
+
업무 피할당자와 결재선은 업무정의리스트에 기본적으로 정의되어있으며, 업무 할당 과정에서 수정할 수 있습니다.
|
|
25
|
+
|
|
26
|
+
- 업무 게시 (post) 유형
|
|
27
|
+
|
|
28
|
+
'업무 게시(post)' 유형의 업무는 시작하는 사람이 해당업무를 시작하고 마무리해서 필요시 관리자의 결재를 위해 제출까지 하는 유형입니다.
|
|
29
|
+
이 유형의 업무는 업무 할당과정이 없이 업무를 시작하는 사람이 바로 피할당자가 되며, 게시와 동시에 업무는 마무리되거나 결재를 위해 제출되게 됩니다.
|
|
30
|
+
|
|
31
|
+
이 업무 작성이 완료되어 '업무 게시(post)'를 하게되면, 결재과정이 없다면, 업무는 바로 완료되어 작성자의 업무 수행 이력에서 찾아볼 수 있게 됩니다.
|
|
32
|
+
결재 과정이 있다면, 작성자의 '나의 할일' 리스트서에 결재가 완료될 때까지 대기하게 됩니다.
|
|
33
|
+
|
|
34
|
+
업무 피할당자와 결재선은 업무정의리스트에 기본적으로 정의되어있으며, 업무 할당 과정에서 수정할 수 있습니다.
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
- 재개: 보류 상태의 유저태스크가 다시 진행 중인 상태가 됩니다.
|
|
43
43
|
- 완료: 진행 중인 유저태스크가 완료 상태가 됩니다.
|
|
44
44
|
|
|
45
|
-
## TODO 리스트
|
|
45
|
+
## TODO 리스트 (나의 할일 리스트)
|
|
46
46
|
|
|
47
47
|
TODO 리스트는 업무 처리에서 아직 해야 할 일들을 기록하고 추적하는 방법 중 하나입니다. 예를 들어, 업무 처리 중에 다음과 같은 상황이 생길 수 있습니다.
|
|
48
48
|
|
|
@@ -54,16 +54,19 @@ TODO 리스트는 업무 처리에서 아직 해야 할 일들을 기록하고
|
|
|
54
54
|
|
|
55
55
|
또한, TODO 리스트는 작성자의 생각을 정리하는 데에도 도움이 됩니다. 작성자가 어떤 일을 해야 하는지 명확하게 파악하고, 일을 처리하는 과정에서 생각이 더해질 경우 리스트에 추가하고, 처리가 완료된 일은 리스트에서 제거하여 업무 처리 상황을 파악할 수 있습니다. 이를 통해 업무 처리의 투명성을 높이고, 업무 처리에 대한 관리와 추적이 용이해집니다.
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## 승인 대기 리스트
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
승인 대기 리스트는 업무 진행자가 자신이 수행한 업무에 대한 검토나 지속적인 추진을 위해서 관리자의 승인을 요청한 것들 중에서 내가 승인 또는 반려 처리해야하는 리스트를 보여줍니다.
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
사용자는 승인 대기 리스트에서 처리하고자 하는 업무를 선택하고 승인 또는 반려 처리를 할 수 있습니다.
|
|
62
|
+
이 과정에서 승인 또는 반려의 사유 등 판단의 근거를 코멘트로 남기도록 하고 있습니다.
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
사용자가 승인 또는 반려한 업무 이력은 '내가 수행한 승인리스트'에서 조회할 수 있습니다.
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
## 내가 수행한 승인리스트
|
|
67
|
+
|
|
68
|
+
내가 수행한 승인리스트는 이미 처리된 승인 업무를 기록하는 리스트입니다.
|
|
69
|
+
|
|
70
|
+
내가 수행한 승인리스트를 유지하는 것은 업무나 작업의 처리상태를 파악하고, 추후에 해당 작업이나 업무를 참조해야 할 때 유용합니다.
|
|
68
71
|
|
|
69
72
|
(이 페이지는 ChatGPT로 작성되었습니다.)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/worklist",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.46",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@operato/event-view": "^1.0.0",
|
|
28
29
|
"@operato/graphql": "^1.0.0",
|
|
29
30
|
"@operato/grist-editor": "^1.0.0",
|
|
30
31
|
"@things-factory/attachment-base": "^6.0.43",
|
|
@@ -36,5 +37,5 @@
|
|
|
36
37
|
"@things-factory/shell": "^6.0.43",
|
|
37
38
|
"moment-timezone": "^0.5.40"
|
|
38
39
|
},
|
|
39
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "0fc79b215a4dabc07d2a73432e09f57252d55d83"
|
|
40
41
|
}
|
|
@@ -31,7 +31,7 @@ export async function assign(
|
|
|
31
31
|
- The previous state of the task must not be Assigned.
|
|
32
32
|
*/
|
|
33
33
|
if (
|
|
34
|
-
activityInstance.state !== ActivityInstanceStatus.
|
|
34
|
+
activityInstance.state !== ActivityInstanceStatus.Issued &&
|
|
35
35
|
activityInstance.state !== ActivityInstanceStatus.PendingAssignment
|
|
36
36
|
) {
|
|
37
37
|
throw new Error(
|
|
@@ -1,18 +1,47 @@
|
|
|
1
1
|
import { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance'
|
|
2
|
-
import {
|
|
2
|
+
import { ActivityInstanceDraft } from '../../service/activity-instance/activity-instance-type'
|
|
3
3
|
import { Activity } from '../../service/activity/activity'
|
|
4
4
|
import { fillActivitySearchKeys } from '../common'
|
|
5
5
|
|
|
6
6
|
export async function draft(
|
|
7
|
-
activityInstance:
|
|
7
|
+
activityInstance: ActivityInstanceDraft,
|
|
8
8
|
context: ResolverContext
|
|
9
9
|
): Promise<ActivityInstance> {
|
|
10
10
|
const { domain, user, tx } = context.state
|
|
11
|
-
const { activityId, input, dueAt } = activityInstance
|
|
11
|
+
const { id, activityId, input, dueAt } = activityInstance
|
|
12
12
|
|
|
13
13
|
var repository = tx.getRepository(Activity)
|
|
14
14
|
var activity = {} as Activity
|
|
15
15
|
|
|
16
|
+
if (id) {
|
|
17
|
+
var previousActivityInstance = await tx.getRepository(ActivityInstance).findOne({
|
|
18
|
+
where: { domain: { id: domain.id }, id },
|
|
19
|
+
relations: ['activity']
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
if (!previousActivityInstance) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
context.t('error.activityInstance not found', {
|
|
25
|
+
activityInstance: id
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (previousActivityInstance.state !== ActivityInstanceStatus.Draft) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
context.t('error.activityInstance state should be draft', {
|
|
33
|
+
activityInstance: id,
|
|
34
|
+
state: previousActivityInstance.state
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
activity = previousActivityInstance.activity
|
|
40
|
+
} else {
|
|
41
|
+
activityInstance.adhocType = 'standard'
|
|
42
|
+
activityInstance.refBy = activityId
|
|
43
|
+
}
|
|
44
|
+
|
|
16
45
|
if (activityId) {
|
|
17
46
|
activity = await repository.findOne({
|
|
18
47
|
where: { domain: { id: domain.id }, id: activityId },
|
|
@@ -28,8 +57,6 @@ export async function draft(
|
|
|
28
57
|
}
|
|
29
58
|
}
|
|
30
59
|
|
|
31
|
-
activityInstance.adhocType = 'standard'
|
|
32
|
-
activityInstance.refBy = activityId
|
|
33
60
|
if (!activityInstance.assignees) {
|
|
34
61
|
activityInstance.assignees = activity.assignees
|
|
35
62
|
}
|
|
@@ -48,7 +75,6 @@ export async function draft(
|
|
|
48
75
|
value: assignee.value
|
|
49
76
|
}
|
|
50
77
|
})
|
|
51
|
-
} else {
|
|
52
78
|
}
|
|
53
79
|
|
|
54
80
|
if (activityInstance.approvalLine) {
|
|
@@ -63,6 +89,7 @@ export async function draft(
|
|
|
63
89
|
const activitySearchKeys = fillActivitySearchKeys(activity?.searchKeys, input)
|
|
64
90
|
|
|
65
91
|
return await tx.getRepository(ActivityInstance).save({
|
|
92
|
+
...previousActivityInstance,
|
|
66
93
|
activityType: activity.activityType,
|
|
67
94
|
uiType: activity.uiType,
|
|
68
95
|
uiSource: activity.uiSource,
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Activity } from '../../service/activity/activity'
|
|
2
|
+
import { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance'
|
|
3
|
+
import { ActivityInstanceIssue } from '../../service/activity-instance/activity-instance-type'
|
|
4
|
+
import {
|
|
5
|
+
createActivityThreadsForAllRoleUsers,
|
|
6
|
+
createActivityThreadsForUsers,
|
|
7
|
+
getSystemUserFromOrgMemberItem,
|
|
8
|
+
createActivityThreadForUser,
|
|
9
|
+
fillActivitySearchKeys
|
|
10
|
+
} from '../common'
|
|
11
|
+
import { submit } from '../activity-thread/submit'
|
|
12
|
+
|
|
13
|
+
export async function issue(
|
|
14
|
+
activityInstance: ActivityInstanceIssue,
|
|
15
|
+
context: ResolverContext
|
|
16
|
+
): Promise<ActivityInstance> {
|
|
17
|
+
const { domain, user, tx } = context.state
|
|
18
|
+
const issuedAt = new Date()
|
|
19
|
+
var {
|
|
20
|
+
id,
|
|
21
|
+
name,
|
|
22
|
+
description,
|
|
23
|
+
assignees,
|
|
24
|
+
uiType,
|
|
25
|
+
uiSource,
|
|
26
|
+
viewType,
|
|
27
|
+
viewSource,
|
|
28
|
+
dueAt,
|
|
29
|
+
priority,
|
|
30
|
+
approvalLine,
|
|
31
|
+
activityId,
|
|
32
|
+
activityType,
|
|
33
|
+
assigneeRole,
|
|
34
|
+
supervisoryRole,
|
|
35
|
+
input
|
|
36
|
+
} = activityInstance
|
|
37
|
+
|
|
38
|
+
var origin = id
|
|
39
|
+
? await tx.getRepository(ActivityInstance).findOne({
|
|
40
|
+
where: { domain: { id: domain.id }, id },
|
|
41
|
+
relations: [
|
|
42
|
+
'domain',
|
|
43
|
+
'activity',
|
|
44
|
+
'assigneeRole',
|
|
45
|
+
'supervisoryRole',
|
|
46
|
+
'updater',
|
|
47
|
+
'creator',
|
|
48
|
+
'starter',
|
|
49
|
+
'terminator'
|
|
50
|
+
]
|
|
51
|
+
})
|
|
52
|
+
: null
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
Prerequisites for a Task to Be Issued.
|
|
56
|
+
- The previous state of the task should be Draft.
|
|
57
|
+
*/
|
|
58
|
+
if (origin && origin.state !== ActivityInstanceStatus.Draft) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
context.t(`error.activity-instance is already issued`, {
|
|
61
|
+
id: id,
|
|
62
|
+
state: origin.state
|
|
63
|
+
})
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var repository = tx.getRepository(Activity)
|
|
68
|
+
var activity =
|
|
69
|
+
origin?.activity ||
|
|
70
|
+
(await repository.findOne({
|
|
71
|
+
where: { domain: { id: domain.id }, id: activityId },
|
|
72
|
+
relations: ['assigneeRole', 'supervisoryRole']
|
|
73
|
+
}))
|
|
74
|
+
|
|
75
|
+
if (!activity) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
context.t('error.activity not found', {
|
|
78
|
+
activity: activityId
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!origin) {
|
|
84
|
+
activityInstance.name = name || activity.name
|
|
85
|
+
activityInstance.description = description || activity.description
|
|
86
|
+
activityInstance.activityType = activityType || activity.activityType
|
|
87
|
+
activityInstance.uiType = uiType || activity.uiType
|
|
88
|
+
activityInstance.uiSource = uiSource || activity.uiSource
|
|
89
|
+
activityInstance.viewType = viewType || activity.viewType
|
|
90
|
+
activityInstance.viewSource = viewSource || activity.viewSource
|
|
91
|
+
activityInstance.assigneeRole = assigneeRole || activity.assigneeRole
|
|
92
|
+
activityInstance.supervisoryRole = supervisoryRole || activity.supervisoryRole
|
|
93
|
+
activityInstance.priority = priority ?? activity.priority
|
|
94
|
+
|
|
95
|
+
if (!assignees || !approvalLine) {
|
|
96
|
+
activityInstance.adhocType = 'standard'
|
|
97
|
+
activityInstance.refBy = activityId
|
|
98
|
+
if (!assignees) {
|
|
99
|
+
assignees = activityInstance.assignees = activity.assignees
|
|
100
|
+
}
|
|
101
|
+
if (!approvalLine) {
|
|
102
|
+
approvalLine = activityInstance.approvalLine = activity.approvalLine
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!dueAt && activity.standardTime) {
|
|
106
|
+
activityInstance.dueAt = new Date(issuedAt.getTime() + activity.standardTime * 1000)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const activitySearchKeys = fillActivitySearchKeys(activity?.searchKeys, input)
|
|
112
|
+
|
|
113
|
+
if (activity.startingType == 'post') {
|
|
114
|
+
/*
|
|
115
|
+
startingType이 'post'이면,
|
|
116
|
+
activityInstance 이슈와 동시에 issuer에게 할당된 activityThread가 생성되고 submit까지 모두 완료되게 된다.
|
|
117
|
+
만일, 결재선이 있다면, 상신되게 된다.
|
|
118
|
+
*/
|
|
119
|
+
const posted = await tx.getRepository(ActivityInstance).save({
|
|
120
|
+
creator: user,
|
|
121
|
+
...origin,
|
|
122
|
+
...activityInstance,
|
|
123
|
+
transaction: 'post',
|
|
124
|
+
activity,
|
|
125
|
+
...activitySearchKeys,
|
|
126
|
+
state: ActivityInstanceStatus.Started,
|
|
127
|
+
domain,
|
|
128
|
+
issuer: user,
|
|
129
|
+
updater: user,
|
|
130
|
+
issuedAt,
|
|
131
|
+
startedAt: issuedAt
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
const thread = await createActivityThreadForUser('post', posted, user, context)
|
|
135
|
+
const data = { ...activityInstance.input, ...activityInstance.output }
|
|
136
|
+
const output = (activity.model || [])
|
|
137
|
+
.filter(item => item.inout === 'inout' || item.inout === 'out')
|
|
138
|
+
.reduce((inout, item) => {
|
|
139
|
+
inout[item.name] = data[item.name]
|
|
140
|
+
return inout
|
|
141
|
+
}, {})
|
|
142
|
+
|
|
143
|
+
submit({ id: thread.id, output }, context)
|
|
144
|
+
|
|
145
|
+
return await tx.getRepository(ActivityInstance).findOneBy({ id: posted.id })
|
|
146
|
+
} else {
|
|
147
|
+
const issued = await tx.getRepository(ActivityInstance).save({
|
|
148
|
+
creator: user,
|
|
149
|
+
...origin,
|
|
150
|
+
...activityInstance,
|
|
151
|
+
transaction: 'issue',
|
|
152
|
+
activity,
|
|
153
|
+
...activitySearchKeys,
|
|
154
|
+
state: ActivityInstanceStatus.Issued,
|
|
155
|
+
domain,
|
|
156
|
+
issuer: user,
|
|
157
|
+
updater: user,
|
|
158
|
+
issuedAt
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const assignedUsers = await Promise.all(
|
|
162
|
+
(assignees || []).map(assignee => getSystemUserFromOrgMemberItem(assignee, context))
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if (assignedUsers.length == 0 && issued.threadsMin === 0 && issued.assigneeRoleId) {
|
|
166
|
+
await createActivityThreadsForAllRoleUsers('issue', issued, context)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (assignedUsers.length > 0) {
|
|
170
|
+
await createActivityThreadsForUsers('issue', issued, assignedUsers, context)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return await tx.getRepository(ActivityInstance).findOneBy({ id: issued.id })
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -24,7 +24,7 @@ export async function pick(id: string, context: ResolverContext): Promise<Activi
|
|
|
24
24
|
- The previous state of the task must not be Assigned.
|
|
25
25
|
*/
|
|
26
26
|
if (
|
|
27
|
-
activityInstance.state !== ActivityInstanceStatus.
|
|
27
|
+
activityInstance.state !== ActivityInstanceStatus.Issued &&
|
|
28
28
|
activityInstance.state !== ActivityInstanceStatus.PendingAssignment
|
|
29
29
|
) {
|
|
30
30
|
throw new Error(
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Role, User } from '@things-factory/auth-base'
|
|
2
2
|
|
|
3
3
|
import { ActivitySearchKeyItem } from '../service/activity/activity-search-key-item-type'
|
|
4
|
-
import {
|
|
4
|
+
import { AssigneeItem } from '../service/activity/activity'
|
|
5
|
+
import { ActivityInstance, ActivityInstanceStatus } from '../service/activity-instance/activity-instance'
|
|
5
6
|
import { ActivityThread, ActivityThreadStatus } from '../service/activity-thread/activity-thread'
|
|
6
7
|
import { Department, Employee, ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'
|
|
7
8
|
import { ActivityInstallations } from './activity-installation/activity-installation-controller'
|
|
@@ -31,7 +32,7 @@ export async function evalActivityInstanceState(
|
|
|
31
32
|
|
|
32
33
|
const activityInstance = await tx.getRepository(ActivityInstance).findOne({
|
|
33
34
|
where: { id },
|
|
34
|
-
relations: ['activityThreads']
|
|
35
|
+
relations: ['activityThreads', 'activity']
|
|
35
36
|
})
|
|
36
37
|
const { threadsMin, activityThreads, state, dueAt } = activityInstance
|
|
37
38
|
|
|
@@ -46,7 +47,7 @@ export async function evalActivityInstanceState(
|
|
|
46
47
|
return {}
|
|
47
48
|
case validThreads.length === 0:
|
|
48
49
|
return {
|
|
49
|
-
state: ActivityInstanceStatus.
|
|
50
|
+
state: ActivityInstanceStatus.Issued
|
|
50
51
|
}
|
|
51
52
|
case threadsMin > validThreads.length:
|
|
52
53
|
return {
|
|
@@ -79,18 +80,50 @@ export async function evalActivityInstanceState(
|
|
|
79
80
|
? ActivityInstanceStatus.Aborted
|
|
80
81
|
: ActivityInstanceStatus.Ended,
|
|
81
82
|
reason: '',
|
|
82
|
-
output:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
output: activityInstance.activity.multiple
|
|
84
|
+
? activityThreads
|
|
85
|
+
.filter(thread => (thread.state = ActivityThreadStatus.Ended))
|
|
86
|
+
.reduce((sum, thread) => {
|
|
87
|
+
sum[thread.assigneeId] = thread.output
|
|
88
|
+
return sum
|
|
89
|
+
}, {} as any)
|
|
90
|
+
: activityThreads[0].output,
|
|
88
91
|
terminatedAt: new Date(),
|
|
89
92
|
terminator: user
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
export async function createActivityThreadForUser(
|
|
98
|
+
transaction: string,
|
|
99
|
+
activityInstance: ActivityInstance,
|
|
100
|
+
assignee: User,
|
|
101
|
+
context: ResolverContext
|
|
102
|
+
): Promise<ActivityThread> {
|
|
103
|
+
const { domain, user, tx } = context.state
|
|
104
|
+
|
|
105
|
+
const threadRepo = tx.getRepository(ActivityThread)
|
|
106
|
+
const now = new Date()
|
|
107
|
+
|
|
108
|
+
const result = await threadRepo.save({
|
|
109
|
+
domain,
|
|
110
|
+
assignee,
|
|
111
|
+
state: ActivityThreadStatus.Assigned,
|
|
112
|
+
activityInstance,
|
|
113
|
+
transaction,
|
|
114
|
+
output: activityInstance.output,
|
|
115
|
+
dueAt: activityInstance.dueAt,
|
|
116
|
+
assignedAt: now,
|
|
117
|
+
creator: user,
|
|
118
|
+
updater: user,
|
|
119
|
+
createdAt: now
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
await updateActivityInstanceState(activityInstance.id, context)
|
|
123
|
+
|
|
124
|
+
return result
|
|
125
|
+
}
|
|
126
|
+
|
|
94
127
|
export async function createActivityThreadsForUsers(
|
|
95
128
|
transaction: string,
|
|
96
129
|
activityInstance: ActivityInstance,
|
|
@@ -114,6 +147,7 @@ export async function createActivityThreadsForUsers(
|
|
|
114
147
|
activityInstance,
|
|
115
148
|
domain,
|
|
116
149
|
transaction,
|
|
150
|
+
output: activityInstance.output,
|
|
117
151
|
creator: user,
|
|
118
152
|
updater: user,
|
|
119
153
|
dueAt: activityInstance.dueAt,
|
package/server/routes.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from '@things-factory/env'
|
|
2
2
|
import { Domain, getDataSource } from '@things-factory/shell'
|
|
3
3
|
import { ScheduleRegisterRequest } from '@things-factory/scheduler-client'
|
|
4
|
-
import {
|
|
4
|
+
import { issue } from './controllers/activity-instance/issue'
|
|
5
5
|
|
|
6
6
|
process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
|
|
7
7
|
/*
|
|
@@ -42,7 +42,7 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
|
42
42
|
tx
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
await
|
|
45
|
+
await issue(
|
|
46
46
|
{
|
|
47
47
|
activityId
|
|
48
48
|
},
|
|
@@ -12,8 +12,7 @@ import { config } from '@things-factory/env'
|
|
|
12
12
|
import { Domain } from '@things-factory/shell'
|
|
13
13
|
import { ApprovalLineItem } from '@things-factory/organization'
|
|
14
14
|
|
|
15
|
-
import { AssigneeItem } from '
|
|
16
|
-
import { Activity, ActivityStatus, ActivityType, ActivityUIType } from './activity'
|
|
15
|
+
import { Activity, ActivityStartingType, ActivityStatus, ActivityType, ActivityUIType, AssigneeItem } from './activity'
|
|
17
16
|
import { ActivityModelItem } from './activity-model-type'
|
|
18
17
|
|
|
19
18
|
const ORMCONFIG = config.get('ormconfig', {})
|
|
@@ -75,6 +74,10 @@ export class ActivityHistory implements HistoryEntityInterface<Activity> {
|
|
|
75
74
|
@Field({ nullable: true })
|
|
76
75
|
startable?: boolean
|
|
77
76
|
|
|
77
|
+
@Column({ nullable: true })
|
|
78
|
+
@Field({ nullable: true })
|
|
79
|
+
startingType?: ActivityStartingType
|
|
80
|
+
|
|
78
81
|
@Column({
|
|
79
82
|
nullable: true
|
|
80
83
|
})
|