@nocobase/app-plugin-office-flows-example 0.0.0-stage → 0.1.0-beta.0
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/CHANGELOG.md +44 -0
- package/README.md +55 -2
- package/dist/client/components/flow-ui.d.ts +111 -0
- package/dist/client/components/flow-ui.d.ts.map +1 -0
- package/dist/client/components/flow-ui.js +175 -0
- package/dist/client/components/flow-ui.js.map +1 -0
- package/dist/client/components/page-container.d.ts +4 -0
- package/dist/client/components/page-container.d.ts.map +1 -0
- package/dist/client/components/page-container.js +6 -0
- package/dist/client/components/page-container.js.map +1 -0
- package/dist/client/components/page-header.d.ts +8 -0
- package/dist/client/components/page-header.d.ts.map +1 -0
- package/dist/client/components/page-header.js +5 -0
- package/dist/client/components/page-header.js.map +1 -0
- package/dist/client/components/ui/badge.d.ts +7 -0
- package/dist/client/components/ui/badge.d.ts.map +1 -0
- package/dist/client/components/ui/badge.js +19 -0
- package/dist/client/components/ui/badge.js.map +1 -0
- package/dist/client/components/ui/button.d.ts +8 -0
- package/dist/client/components/ui/button.d.ts.map +1 -0
- package/dist/client/components/ui/button.js +25 -0
- package/dist/client/components/ui/button.js.map +1 -0
- package/dist/client/components/ui/card.d.ts +11 -0
- package/dist/client/components/ui/card.d.ts.map +1 -0
- package/dist/client/components/ui/card.js +19 -0
- package/dist/client/components/ui/card.js.map +1 -0
- package/dist/client/components/ui/input.d.ts +4 -0
- package/dist/client/components/ui/input.d.ts.map +1 -0
- package/dist/client/components/ui/input.js +8 -0
- package/dist/client/components/ui/input.js.map +1 -0
- package/dist/client/components/ui/select.d.ts +16 -0
- package/dist/client/components/ui/select.d.ts.map +1 -0
- package/dist/client/components/ui/select.js +36 -0
- package/dist/client/components/ui/select.js.map +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/lib/api.d.ts +93 -0
- package/dist/client/lib/api.d.ts.map +1 -0
- package/dist/client/lib/api.js +67 -0
- package/dist/client/lib/api.js.map +1 -0
- package/dist/client/lib/format.d.ts +4 -0
- package/dist/client/lib/format.d.ts.map +1 -0
- package/dist/client/lib/format.js +8 -0
- package/dist/client/lib/format.js.map +1 -0
- package/dist/client/lib/labels.d.ts +5 -0
- package/dist/client/lib/labels.d.ts.map +1 -0
- package/dist/client/lib/labels.js +38 -0
- package/dist/client/lib/labels.js.map +1 -0
- package/dist/client/lib/use-loader.d.ts +10 -0
- package/dist/client/lib/use-loader.d.ts.map +1 -0
- package/dist/client/lib/use-loader.js +43 -0
- package/dist/client/lib/use-loader.js.map +1 -0
- package/dist/client/lib/utils.d.ts +2 -0
- package/dist/client/lib/utils.d.ts.map +1 -0
- package/dist/client/lib/utils.js +2 -0
- package/dist/client/lib/utils.js.map +1 -0
- package/dist/client/locales/en-US.d.ts +99 -0
- package/dist/client/locales/en-US.d.ts.map +1 -0
- package/dist/client/locales/en-US.js +92 -0
- package/dist/client/locales/en-US.js.map +1 -0
- package/dist/client/locales/index.d.ts +4 -0
- package/dist/client/locales/index.d.ts.map +1 -0
- package/dist/client/locales/index.js +7 -0
- package/dist/client/locales/index.js.map +1 -0
- package/dist/client/locales/zh-CN.d.ts +4 -0
- package/dist/client/locales/zh-CN.d.ts.map +1 -0
- package/dist/client/locales/zh-CN.js +92 -0
- package/dist/client/locales/zh-CN.js.map +1 -0
- package/dist/client/pages/configuration.d.ts +4 -0
- package/dist/client/pages/configuration.d.ts.map +1 -0
- package/dist/client/pages/configuration.js +34 -0
- package/dist/client/pages/configuration.js.map +1 -0
- package/dist/client/pages/data-requests.d.ts +3 -0
- package/dist/client/pages/data-requests.d.ts.map +1 -0
- package/dist/client/pages/data-requests.js +216 -0
- package/dist/client/pages/data-requests.js.map +1 -0
- package/dist/client/pages/incoming.d.ts +3 -0
- package/dist/client/pages/incoming.d.ts.map +1 -0
- package/dist/client/pages/incoming.js +128 -0
- package/dist/client/pages/incoming.js.map +1 -0
- package/dist/client/pages/tasks.d.ts +3 -0
- package/dist/client/pages/tasks.d.ts.map +1 -0
- package/dist/client/pages/tasks.js +116 -0
- package/dist/client/pages/tasks.js.map +1 -0
- package/dist/client/plugin.d.ts +4 -0
- package/dist/client/plugin.d.ts.map +1 -0
- package/dist/client/plugin.js +10 -0
- package/dist/client/plugin.js.map +1 -0
- package/dist/client/routes.d.ts +4 -0
- package/dist/client/routes.d.ts.map +1 -0
- package/dist/client/routes.js +51 -0
- package/dist/client/routes.js.map +1 -0
- package/dist/database/migrations/.manifest.json +9 -0
- package/dist/database/migrations/202610010001_office_flows_example_create_collections.d.ts +4 -0
- package/dist/database/migrations/202610010001_office_flows_example_create_collections.d.ts.map +1 -0
- package/dist/database/migrations/202610010001_office_flows_example_create_collections.js +280 -0
- package/dist/database/migrations/202610010001_office_flows_example_create_collections.js.map +1 -0
- package/dist/database/seeds/.manifest.json +9 -0
- package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.d.ts +10 -0
- package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.d.ts.map +1 -0
- package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.js +104 -0
- package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.js.map +1 -0
- package/dist/server/calendar.d.ts +35 -0
- package/dist/server/calendar.d.ts.map +1 -0
- package/dist/server/calendar.js +103 -0
- package/dist/server/calendar.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/lifecycles/data-request.d.ts +36 -0
- package/dist/server/lifecycles/data-request.d.ts.map +1 -0
- package/dist/server/lifecycles/data-request.js +182 -0
- package/dist/server/lifecycles/data-request.js.map +1 -0
- package/dist/server/lifecycles/extraction.d.ts +21 -0
- package/dist/server/lifecycles/extraction.d.ts.map +1 -0
- package/dist/server/lifecycles/extraction.js +60 -0
- package/dist/server/lifecycles/extraction.js.map +1 -0
- package/dist/server/lifecycles/incoming.d.ts +27 -0
- package/dist/server/lifecycles/incoming.d.ts.map +1 -0
- package/dist/server/lifecycles/incoming.js +177 -0
- package/dist/server/lifecycles/incoming.js.map +1 -0
- package/dist/server/lifecycles/index.d.ts +8 -0
- package/dist/server/lifecycles/index.d.ts.map +1 -0
- package/dist/server/lifecycles/index.js +20 -0
- package/dist/server/lifecycles/index.js.map +1 -0
- package/dist/server/lifecycles/tasks.d.ts +63 -0
- package/dist/server/lifecycles/tasks.d.ts.map +1 -0
- package/dist/server/lifecycles/tasks.js +259 -0
- package/dist/server/lifecycles/tasks.js.map +1 -0
- package/dist/server/plugin.d.ts +4 -0
- package/dist/server/plugin.d.ts.map +1 -0
- package/dist/server/plugin.js +16 -0
- package/dist/server/plugin.js.map +1 -0
- package/dist/server/providers/index.d.ts +4 -0
- package/dist/server/providers/index.d.ts.map +1 -0
- package/dist/server/providers/index.js +6 -0
- package/dist/server/providers/index.js.map +1 -0
- package/dist/server/providers/office-flows.d.ts +23 -0
- package/dist/server/providers/office-flows.d.ts.map +1 -0
- package/dist/server/providers/office-flows.js +90 -0
- package/dist/server/providers/office-flows.js.map +1 -0
- package/dist/server/routes/index.d.ts +8 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +553 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/schemas.d.ts +157 -0
- package/dist/server/routes/schemas.d.ts.map +1 -0
- package/dist/server/routes/schemas.js +188 -0
- package/dist/server/routes/schemas.js.map +1 -0
- package/dist/server/scope.d.ts +23 -0
- package/dist/server/scope.d.ts.map +1 -0
- package/dist/server/scope.js +23 -0
- package/dist/server/scope.js.map +1 -0
- package/dist/server/services/office-flows.d.ts +151 -0
- package/dist/server/services/office-flows.d.ts.map +1 -0
- package/dist/server/services/office-flows.js +603 -0
- package/dist/server/services/office-flows.js.map +1 -0
- package/dist/server/services/store.d.ts +119 -0
- package/dist/server/services/store.d.ts.map +1 -0
- package/dist/server/services/store.js +389 -0
- package/dist/server/services/store.js.map +1 -0
- package/dist/server/tokens.d.ts +4 -0
- package/dist/server/tokens.d.ts.map +1 -0
- package/dist/server/tokens.js +3 -0
- package/dist/server/tokens.js.map +1 -0
- package/dist/shared/data-request.d.ts +73 -0
- package/dist/shared/data-request.d.ts.map +1 -0
- package/dist/shared/data-request.js +182 -0
- package/dist/shared/data-request.js.map +1 -0
- package/dist/shared/fields.d.ts +12 -0
- package/dist/shared/fields.d.ts.map +1 -0
- package/dist/shared/fields.js +48 -0
- package/dist/shared/fields.js.map +1 -0
- package/dist/shared/people.d.ts +29 -0
- package/dist/shared/people.d.ts.map +1 -0
- package/dist/shared/people.js +54 -0
- package/dist/shared/people.js.map +1 -0
- package/dist/shared/routes.d.ts +7 -0
- package/dist/shared/routes.d.ts.map +1 -0
- package/dist/shared/routes.js +7 -0
- package/dist/shared/routes.js.map +1 -0
- package/dist/shared/text.d.ts +3 -0
- package/dist/shared/text.d.ts.map +1 -0
- package/dist/shared/text.js +9 -0
- package/dist/shared/text.js.map +1 -0
- package/package.json +72 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { defineSeed } from '@nocobase/db';
|
|
2
|
+
/**
|
|
3
|
+
* Demonstration configuration: departments with the people a distribution
|
|
4
|
+
* row carries, company management groups, and the 2026 public holidays.
|
|
5
|
+
* Two departments share a head and three share a leader, so the pages can
|
|
6
|
+
* show one reminder reaching a person who appears in several rows.
|
|
7
|
+
*/
|
|
8
|
+
const seed = defineSeed({
|
|
9
|
+
name: '202610010002_office_flows_example_seed_configuration',
|
|
10
|
+
async run(context) {
|
|
11
|
+
const repository = (name) => context.repository(name);
|
|
12
|
+
await repository('officeFlowsDepartments').createMany({
|
|
13
|
+
values: [
|
|
14
|
+
{
|
|
15
|
+
name: '信息技术部',
|
|
16
|
+
clerks: ['huangtao'],
|
|
17
|
+
heads: ['xulei'],
|
|
18
|
+
leaders: ['mahui'],
|
|
19
|
+
sort: 1,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: '财务部',
|
|
23
|
+
clerks: ['gaoyan', 'linfeng'],
|
|
24
|
+
heads: ['heming'],
|
|
25
|
+
leaders: ['mahui'],
|
|
26
|
+
sort: 2,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: '工会',
|
|
30
|
+
clerks: ['luoxin'],
|
|
31
|
+
heads: ['heming'],
|
|
32
|
+
leaders: ['songyu'],
|
|
33
|
+
sort: 3,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: '董事会办公室',
|
|
37
|
+
clerks: ['tangjun'],
|
|
38
|
+
heads: ['fanqing'],
|
|
39
|
+
leaders: ['songyu'],
|
|
40
|
+
sort: 4,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: '风险管理部',
|
|
44
|
+
clerks: ['guoning'],
|
|
45
|
+
heads: ['denghui'],
|
|
46
|
+
leaders: ['mahui'],
|
|
47
|
+
sort: 5,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
await repository('officeFlowsManagementGroups').createMany({
|
|
52
|
+
values: [
|
|
53
|
+
{ name: '公司领导', members: ['yeqing', 'caobin'], sort: 1 },
|
|
54
|
+
{ name: '董事会', members: ['jiangli', 'yeqing'], sort: 2 },
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
// 国务院办公厅关于2026年部分节假日安排的通知(国办发明电〔2025〕7号)
|
|
58
|
+
const holiday = (name, dates) => dates.map((date) => ({ date, kind: 'holiday', name }));
|
|
59
|
+
const workday = (name, dates) => dates.map((date) => ({ date, kind: 'workday', name: `${name}调休上班` }));
|
|
60
|
+
const [first, ...rest] = [
|
|
61
|
+
...holiday('元旦', ['2026-01-01', '2026-01-02', '2026-01-03']),
|
|
62
|
+
...workday('元旦', ['2026-01-04']),
|
|
63
|
+
...holiday('春节', [
|
|
64
|
+
'2026-02-15',
|
|
65
|
+
'2026-02-16',
|
|
66
|
+
'2026-02-17',
|
|
67
|
+
'2026-02-18',
|
|
68
|
+
'2026-02-19',
|
|
69
|
+
'2026-02-20',
|
|
70
|
+
'2026-02-21',
|
|
71
|
+
'2026-02-22',
|
|
72
|
+
'2026-02-23',
|
|
73
|
+
]),
|
|
74
|
+
...workday('春节', ['2026-02-14', '2026-02-28']),
|
|
75
|
+
...holiday('清明节', ['2026-04-04', '2026-04-05', '2026-04-06']),
|
|
76
|
+
...holiday('劳动节', [
|
|
77
|
+
'2026-05-01',
|
|
78
|
+
'2026-05-02',
|
|
79
|
+
'2026-05-03',
|
|
80
|
+
'2026-05-04',
|
|
81
|
+
'2026-05-05',
|
|
82
|
+
]),
|
|
83
|
+
...workday('劳动节', ['2026-05-09']),
|
|
84
|
+
...holiday('端午节', ['2026-06-19', '2026-06-20', '2026-06-21']),
|
|
85
|
+
...holiday('中秋节', ['2026-09-25', '2026-09-26', '2026-09-27']),
|
|
86
|
+
...holiday('国庆节', [
|
|
87
|
+
'2026-10-01',
|
|
88
|
+
'2026-10-02',
|
|
89
|
+
'2026-10-03',
|
|
90
|
+
'2026-10-04',
|
|
91
|
+
'2026-10-05',
|
|
92
|
+
'2026-10-06',
|
|
93
|
+
'2026-10-07',
|
|
94
|
+
]),
|
|
95
|
+
...workday('国庆节', ['2026-09-20', '2026-10-10']),
|
|
96
|
+
];
|
|
97
|
+
await repository('officeFlowsHolidays').createMany({
|
|
98
|
+
values: [first, ...rest],
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
export default seed;
|
|
103
|
+
//# sourceMappingURL=202610010002_office_flows_example_seed_configuration.js.map
|
|
104
|
+
// @nocobase/task-manifest v1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"202610010002_office_flows_example_seed_configuration.js","sourceRoot":"","sources":["../../../database/seeds/202610010002_office_flows_example_seed_configuration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Frequency } from '../shared/data-request.js';
|
|
2
|
+
/** A holiday, or a weekend day worked in exchange for one (调休上班). */
|
|
3
|
+
export interface CalendarEntry {
|
|
4
|
+
readonly date: string;
|
|
5
|
+
readonly kind: 'holiday' | 'workday';
|
|
6
|
+
}
|
|
7
|
+
export interface WorkCalendar {
|
|
8
|
+
isWorkday(date: string): boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function createWorkCalendar(entries: readonly CalendarEntry[]): WorkCalendar;
|
|
11
|
+
/** The date itself when it is a workday, else the next workday. */
|
|
12
|
+
export declare function nextWorkday(date: string, calendar: WorkCalendar): string;
|
|
13
|
+
export interface ExtractionSchedule {
|
|
14
|
+
readonly frequency: Frequency | '';
|
|
15
|
+
readonly firstUseDate: string;
|
|
16
|
+
readonly lastDeliveryDate: string;
|
|
17
|
+
readonly quarterDay: number | null;
|
|
18
|
+
readonly monthDay: number | null;
|
|
19
|
+
readonly weekDay: number | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One date per period between the first use and the last delivery, before
|
|
23
|
+
* holidays are taken into account. "Once" and "other" have no periods: a
|
|
24
|
+
* one-time request is delivered on its own date, and another frequency is
|
|
25
|
+
* scheduled by hand.
|
|
26
|
+
*/
|
|
27
|
+
export declare function nominalDates(schedule: ExtractionSchedule): string[];
|
|
28
|
+
/**
|
|
29
|
+
* The days an extraction task is due. A date on a weekend or a public
|
|
30
|
+
* holiday moves to the next workday, or to the workday before when that
|
|
31
|
+
* would pass the last delivery date; periods that land on the same workday
|
|
32
|
+
* share one task.
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractionDates(schedule: ExtractionSchedule, calendar: WorkCalendar): string[];
|
|
35
|
+
//# sourceMappingURL=calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../server/calendar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,aAAa,EAAE,GAChC,YAAY,CAUd;AAeD,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CAKxE;AASD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAiDnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,YAAY,GACrB,MAAM,EAAE,CAWV"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export function createWorkCalendar(entries) {
|
|
2
|
+
const kinds = new Map(entries.map((entry) => [entry.date, entry.kind]));
|
|
3
|
+
return {
|
|
4
|
+
isWorkday(date) {
|
|
5
|
+
const kind = kinds.get(date);
|
|
6
|
+
if (kind)
|
|
7
|
+
return kind === 'workday';
|
|
8
|
+
const weekday = new Date(`${date}T00:00:00Z`).getUTCDay();
|
|
9
|
+
return weekday !== 0 && weekday !== 6;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function shift(date, days) {
|
|
14
|
+
const time = Date.parse(`${date}T00:00:00Z`) + days * 86_400_000;
|
|
15
|
+
return new Date(time).toISOString().slice(0, 10);
|
|
16
|
+
}
|
|
17
|
+
function daysInMonth(year, month) {
|
|
18
|
+
return new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
19
|
+
}
|
|
20
|
+
function pad(value) {
|
|
21
|
+
return String(value).padStart(2, '0');
|
|
22
|
+
}
|
|
23
|
+
/** The date itself when it is a workday, else the next workday. */
|
|
24
|
+
export function nextWorkday(date, calendar) {
|
|
25
|
+
let current = date;
|
|
26
|
+
for (let step = 0; step < 366 && !calendar.isWorkday(current); step += 1)
|
|
27
|
+
current = shift(current, 1);
|
|
28
|
+
return current;
|
|
29
|
+
}
|
|
30
|
+
function previousWorkday(date, calendar) {
|
|
31
|
+
let current = date;
|
|
32
|
+
for (let step = 0; step < 366 && !calendar.isWorkday(current); step += 1)
|
|
33
|
+
current = shift(current, -1);
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One date per period between the first use and the last delivery, before
|
|
38
|
+
* holidays are taken into account. "Once" and "other" have no periods: a
|
|
39
|
+
* one-time request is delivered on its own date, and another frequency is
|
|
40
|
+
* scheduled by hand.
|
|
41
|
+
*/
|
|
42
|
+
export function nominalDates(schedule) {
|
|
43
|
+
const { firstUseDate: first, lastDeliveryDate: last } = schedule;
|
|
44
|
+
if (!first || !last || last < first)
|
|
45
|
+
return [];
|
|
46
|
+
const dates = [];
|
|
47
|
+
const startYear = Number(first.slice(0, 4));
|
|
48
|
+
const endYear = Number(last.slice(0, 4));
|
|
49
|
+
const inRange = (date) => {
|
|
50
|
+
if (date >= first && date <= last)
|
|
51
|
+
dates.push(date);
|
|
52
|
+
};
|
|
53
|
+
switch (schedule.frequency) {
|
|
54
|
+
case 'daily':
|
|
55
|
+
for (let date = first; date <= last; date = shift(date, 1))
|
|
56
|
+
dates.push(date);
|
|
57
|
+
break;
|
|
58
|
+
case 'weekly': {
|
|
59
|
+
const target = schedule.weekDay ?? 1;
|
|
60
|
+
// getUTCDay: 0 is Sunday; the form counts Monday as 1 and Sunday as 7.
|
|
61
|
+
const offset = (target % 7) - new Date(`${first}T00:00:00Z`).getUTCDay();
|
|
62
|
+
for (let date = shift(first, (offset + 7) % 7); date <= last; date = shift(date, 7))
|
|
63
|
+
dates.push(date);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case 'monthly':
|
|
67
|
+
for (let year = startYear; year <= endYear; year += 1)
|
|
68
|
+
for (let month = 1; month <= 12; month += 1) {
|
|
69
|
+
const day = Math.min(schedule.monthDay ?? 1, daysInMonth(year, month));
|
|
70
|
+
inRange(`${year}-${pad(month)}-${pad(day)}`);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
case 'quarterly':
|
|
74
|
+
for (let year = startYear; year <= endYear; year += 1)
|
|
75
|
+
for (const month of [1, 4, 7, 10]) {
|
|
76
|
+
const start = `${year}-${pad(month)}-01`;
|
|
77
|
+
const end = `${year}-${pad(month + 2)}-${pad(daysInMonth(year, month + 2))}`;
|
|
78
|
+
const date = shift(start, (schedule.quarterDay ?? 1) - 1);
|
|
79
|
+
inRange(date > end ? end : date);
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return dates;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The days an extraction task is due. A date on a weekend or a public
|
|
89
|
+
* holiday moves to the next workday, or to the workday before when that
|
|
90
|
+
* would pass the last delivery date; periods that land on the same workday
|
|
91
|
+
* share one task.
|
|
92
|
+
*/
|
|
93
|
+
export function extractionDates(schedule, calendar) {
|
|
94
|
+
const due = new Set();
|
|
95
|
+
for (const date of nominalDates(schedule)) {
|
|
96
|
+
const forward = nextWorkday(date, calendar);
|
|
97
|
+
due.add(forward <= schedule.lastDeliveryDate
|
|
98
|
+
? forward
|
|
99
|
+
: previousWorkday(date, calendar));
|
|
100
|
+
}
|
|
101
|
+
return [...due].filter((date) => date >= schedule.firstUseDate).sort();
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.js","sourceRoot":"","sources":["../../server/calendar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type EffectDefinition, type Lifecycle, type LifecycleRecord } from '@nocobase/lifecycle';
|
|
2
|
+
import { type DataRequestForm } from '../../shared/data-request.js';
|
|
3
|
+
import { type OfficeStore } from '../services/store.js';
|
|
4
|
+
export type DataRequestState = 'draft' | 'level1Review' | 'level2Review' | 'level3Review' | 'accepting' | 'completed' | 'exited';
|
|
5
|
+
export interface DataRequest extends LifecycleRecord {
|
|
6
|
+
readonly number: string;
|
|
7
|
+
readonly applicantId: string;
|
|
8
|
+
readonly subject: string;
|
|
9
|
+
readonly frequency: string;
|
|
10
|
+
readonly deliveryDate: string | null;
|
|
11
|
+
readonly approverId: string | null;
|
|
12
|
+
readonly acceptedAt: string | null;
|
|
13
|
+
readonly status: DataRequestState;
|
|
14
|
+
}
|
|
15
|
+
export interface OfficeServices {
|
|
16
|
+
readonly store: OfficeStore;
|
|
17
|
+
}
|
|
18
|
+
export interface DataRequestTypes {
|
|
19
|
+
record: DataRequest;
|
|
20
|
+
state: DataRequestState;
|
|
21
|
+
services: OfficeServices;
|
|
22
|
+
}
|
|
23
|
+
/** The stored record read back as the form it was filled in from. */
|
|
24
|
+
export declare function formOf(record: Record<string, unknown>): DataRequestForm;
|
|
25
|
+
/**
|
|
26
|
+
* A one-time request gets its single extraction task as soon as it reaches
|
|
27
|
+
* acceptance, dated on its delivery date or the next workday after it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const createOneTimeExtraction: EffectDefinition<DataRequestTypes>;
|
|
30
|
+
/**
|
|
31
|
+
* A data usage request: three levels of managers, then acceptance, where the
|
|
32
|
+
* extraction tasks are created and followed. Acceptance cannot return the
|
|
33
|
+
* request once any task exists, and cannot finish while one is open.
|
|
34
|
+
*/
|
|
35
|
+
export declare const dataRequestLifecycle: Lifecycle<DataRequestTypes>;
|
|
36
|
+
//# sourceMappingURL=data-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-request.d.ts","sourceRoot":"","sources":["../../../server/lifecycles/data-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EAErB,KAAK,SAAS,EACd,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGtE,MAAM,MAAM,gBAAgB,GACxB,OAAO,GACP,cAAc,GACd,cAAc,GACd,cAAc,GACd,WAAW,GACX,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAUD,qEAAqE;AACrE,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CA4BvE;AAoCD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,CAAC,gBAAgB,CAmBnE,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,gBAAgB,CAoGzD,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { defineEffect, defineLifecycle, LifecycleError, } from '@nocobase/lifecycle';
|
|
2
|
+
import { validateDataRequest, } from '../../shared/data-request.js';
|
|
3
|
+
import { DATA_REQUEST_ROLES } from '../../shared/people.js';
|
|
4
|
+
import { nextWorkday } from '../calendar.js';
|
|
5
|
+
import { COLLECTIONS } from '../scope.js';
|
|
6
|
+
import { idOf, people } from '../services/store.js';
|
|
7
|
+
import { text } from '../../shared/text.js';
|
|
8
|
+
const NEXT_APPROVER = {
|
|
9
|
+
level1Review: DATA_REQUEST_ROLES.level2,
|
|
10
|
+
level2Review: DATA_REQUEST_ROLES.level3,
|
|
11
|
+
level3Review: DATA_REQUEST_ROLES.acceptor,
|
|
12
|
+
};
|
|
13
|
+
/** The stored record read back as the form it was filled in from. */
|
|
14
|
+
export function formOf(record) {
|
|
15
|
+
const str = (value) => typeof value === 'string' ? value : '';
|
|
16
|
+
const number = (value) => value === null || value === undefined ? null : Number(value);
|
|
17
|
+
const flag = (value) => value === null || value === undefined ? null : Boolean(value);
|
|
18
|
+
return {
|
|
19
|
+
subject: str(record.subject),
|
|
20
|
+
reason: str(record.reason),
|
|
21
|
+
volume: str(record.volume),
|
|
22
|
+
frequency: str(record.frequency),
|
|
23
|
+
deliveryDate: str(record.deliveryDate),
|
|
24
|
+
firstUseDate: str(record.firstUseDate),
|
|
25
|
+
lastDeliveryDate: str(record.lastDeliveryDate),
|
|
26
|
+
quarterDay: number(record.quarterDay),
|
|
27
|
+
monthDay: number(record.monthDay),
|
|
28
|
+
weekDay: number(record.weekDay),
|
|
29
|
+
frequencyNote: str(record.frequencyNote),
|
|
30
|
+
scope: str(record.scope),
|
|
31
|
+
consumers: people(record.consumers),
|
|
32
|
+
fileShieldAccepted: flag(record.fileShieldAccepted),
|
|
33
|
+
fileShieldScope: str(record.fileShieldScope),
|
|
34
|
+
fileShieldCopy: flag(record.fileShieldCopy),
|
|
35
|
+
fileShieldValidUntil: str(record.fileShieldValidUntil),
|
|
36
|
+
ndaFiles: people(record.ndaFiles),
|
|
37
|
+
securityFiles: people(record.securityFiles),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function isApprover({ record, actor }) {
|
|
41
|
+
return actor.id === record.approverId;
|
|
42
|
+
}
|
|
43
|
+
function isAcceptor({ record, actor }) {
|
|
44
|
+
return (record.status === 'accepting' && actor.id === DATA_REQUEST_ROLES.acceptor);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The acceptor may act, but not while extraction tasks in `statuses` exist.
|
|
48
|
+
* Who acts is a permission; the tasks are a precondition the acceptor can
|
|
49
|
+
* clear, so the route answers that refusal as 400 FAILED_PRECONDITION.
|
|
50
|
+
*/
|
|
51
|
+
async function acceptorWithout(context, statuses, refusal) {
|
|
52
|
+
if (!isAcceptor(context))
|
|
53
|
+
return false;
|
|
54
|
+
const open = await context.services.store.countExtractions(context.record.id, statuses);
|
|
55
|
+
return open === 0 || { ...refusal, kind: 'precondition' };
|
|
56
|
+
}
|
|
57
|
+
function reasonRequired(input) {
|
|
58
|
+
return typeof input.reason === 'string' && input.reason.trim()
|
|
59
|
+
? null
|
|
60
|
+
: 'Give a reason.';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A one-time request gets its single extraction task as soon as it reaches
|
|
64
|
+
* acceptance, dated on its delivery date or the next workday after it.
|
|
65
|
+
*/
|
|
66
|
+
export const createOneTimeExtraction = defineEffect({
|
|
67
|
+
name: 'dataRequests.createOneTimeExtraction',
|
|
68
|
+
retry: { attempts: 3, backoffMs: 1_000 },
|
|
69
|
+
async run({ record, services }) {
|
|
70
|
+
if (record.frequency !== 'once' || !record.deliveryDate)
|
|
71
|
+
return { skipped: true };
|
|
72
|
+
const calendar = await services.store.calendar();
|
|
73
|
+
const created = await services.store.createExtraction({
|
|
74
|
+
requestId: idOf(record.id),
|
|
75
|
+
periodKey: 'once',
|
|
76
|
+
origin: 'once',
|
|
77
|
+
scheduledDate: nextWorkday(record.deliveryDate, calendar),
|
|
78
|
+
topic: `${record.subject}(一次性)`,
|
|
79
|
+
requirement: '',
|
|
80
|
+
executorIds: DATA_REQUEST_ROLES.executors,
|
|
81
|
+
});
|
|
82
|
+
return { created: created?.number ?? null };
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* A data usage request: three levels of managers, then acceptance, where the
|
|
87
|
+
* extraction tasks are created and followed. Acceptance cannot return the
|
|
88
|
+
* request once any task exists, and cannot finish while one is open.
|
|
89
|
+
*/
|
|
90
|
+
export const dataRequestLifecycle = defineLifecycle({
|
|
91
|
+
name: 'dataRequests',
|
|
92
|
+
collection: COLLECTIONS.dataRequests,
|
|
93
|
+
initial: 'draft',
|
|
94
|
+
states: [
|
|
95
|
+
'draft',
|
|
96
|
+
'level1Review',
|
|
97
|
+
'level2Review',
|
|
98
|
+
'level3Review',
|
|
99
|
+
'accepting',
|
|
100
|
+
{ name: 'completed', final: true },
|
|
101
|
+
{ name: 'exited', final: true },
|
|
102
|
+
],
|
|
103
|
+
transitions: {
|
|
104
|
+
submit: {
|
|
105
|
+
title: '提交',
|
|
106
|
+
from: 'draft',
|
|
107
|
+
to: 'level1Review',
|
|
108
|
+
guard: ({ record, actor }) => actor.id === record.applicantId,
|
|
109
|
+
// An incomplete form is the request's state, not a bad request to
|
|
110
|
+
// submit it: INVALID_STATE, which answers 400 FAILED_PRECONDITION.
|
|
111
|
+
set: ({ record }) => {
|
|
112
|
+
const errors = validateDataRequest(formOf(record));
|
|
113
|
+
if (Object.keys(errors).length)
|
|
114
|
+
throw new LifecycleError('INVALID_STATE', Object.values(errors).join(';'));
|
|
115
|
+
return { approverId: DATA_REQUEST_ROLES.level1, returnReason: null };
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
approve: {
|
|
119
|
+
title: '同意',
|
|
120
|
+
from: ['level1Review', 'level2Review', 'level3Review'],
|
|
121
|
+
to: ['level2Review', 'level3Review', 'accepting'],
|
|
122
|
+
route: ({ record }) => record.status === 'level1Review'
|
|
123
|
+
? 'level2Review'
|
|
124
|
+
: record.status === 'level2Review'
|
|
125
|
+
? 'level3Review'
|
|
126
|
+
: 'accepting',
|
|
127
|
+
guard: isApprover,
|
|
128
|
+
set: ({ record, now }) => ({
|
|
129
|
+
approverId: NEXT_APPROVER[record.status] ?? null,
|
|
130
|
+
...(record.status === 'level3Review' && !record.acceptedAt
|
|
131
|
+
? { acceptedAt: now.toISOString() }
|
|
132
|
+
: {}),
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
returnToApplicant: {
|
|
136
|
+
title: '退回申请人',
|
|
137
|
+
from: ['level1Review', 'level2Review', 'level3Review'],
|
|
138
|
+
to: 'draft',
|
|
139
|
+
guard: isApprover,
|
|
140
|
+
validate: reasonRequired,
|
|
141
|
+
set: ({ input }) => ({
|
|
142
|
+
approverId: null,
|
|
143
|
+
returnReason: text(input.reason),
|
|
144
|
+
}),
|
|
145
|
+
},
|
|
146
|
+
acceptanceReturn: {
|
|
147
|
+
title: '返回申请人',
|
|
148
|
+
from: 'accepting',
|
|
149
|
+
to: 'draft',
|
|
150
|
+
// Not once any extraction task exists, running or finished.
|
|
151
|
+
guard: (context) => acceptorWithout(context, ['pending', 'completed'], {
|
|
152
|
+
code: 'extractionsExist',
|
|
153
|
+
message: 'The request has extraction tasks; it can no longer go back to the applicant.',
|
|
154
|
+
}),
|
|
155
|
+
validate: reasonRequired,
|
|
156
|
+
set: ({ input }) => ({
|
|
157
|
+
approverId: null,
|
|
158
|
+
returnReason: text(input.reason),
|
|
159
|
+
}),
|
|
160
|
+
},
|
|
161
|
+
complete: {
|
|
162
|
+
title: '提交办结',
|
|
163
|
+
from: 'accepting',
|
|
164
|
+
to: 'completed',
|
|
165
|
+
// Not while an extraction task is still open.
|
|
166
|
+
guard: (context) => acceptorWithout(context, ['pending'], {
|
|
167
|
+
code: 'extractionsOpen',
|
|
168
|
+
message: 'An extraction task is still open; finish or void it first.',
|
|
169
|
+
}),
|
|
170
|
+
set: () => ({ approverId: null }),
|
|
171
|
+
},
|
|
172
|
+
exit: {
|
|
173
|
+
title: '退出审批',
|
|
174
|
+
from: 'accepting',
|
|
175
|
+
to: 'exited',
|
|
176
|
+
guard: isAcceptor,
|
|
177
|
+
set: () => ({ approverId: null }),
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
onEnter: { accepting: [createOneTimeExtraction] },
|
|
181
|
+
});
|
|
182
|
+
//# sourceMappingURL=data-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-request.js","sourceRoot":"","sources":["../../../server/lifecycles/data-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Lifecycle, type LifecycleRecord } from '@nocobase/lifecycle';
|
|
2
|
+
import type { OfficeServices } from './data-request.js';
|
|
3
|
+
export type ExtractionState = 'pending' | 'completed' | 'voided';
|
|
4
|
+
export interface Extraction extends LifecycleRecord {
|
|
5
|
+
readonly status: ExtractionState;
|
|
6
|
+
readonly executorIds: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface ExtractionTypes {
|
|
9
|
+
record: Extraction;
|
|
10
|
+
state: ExtractionState;
|
|
11
|
+
services: OfficeServices;
|
|
12
|
+
}
|
|
13
|
+
/** The processing fields a task must have before it can be submitted. */
|
|
14
|
+
export declare const EXTRACTION_REQUIRED: readonly (readonly [string, string])[];
|
|
15
|
+
/**
|
|
16
|
+
* One extraction task of a data usage request. Its approval has no
|
|
17
|
+
* requirements, so it is processed once and submitted, or voided by the
|
|
18
|
+
* acceptor.
|
|
19
|
+
*/
|
|
20
|
+
export declare const extractionLifecycle: Lifecycle<ExtractionTypes>;
|
|
21
|
+
//# sourceMappingURL=extraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../../server/lifecycles/extraction.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EASrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,eAAe,CA8CvD,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { defineLifecycle, LifecycleError, } from '@nocobase/lifecycle';
|
|
2
|
+
import { DATA_REQUEST_ROLES } from '../../shared/people.js';
|
|
3
|
+
import { COLLECTIONS } from '../scope.js';
|
|
4
|
+
import { people } from '../services/store.js';
|
|
5
|
+
import { text } from '../../shared/text.js';
|
|
6
|
+
/** The processing fields a task must have before it can be submitted. */
|
|
7
|
+
export const EXTRACTION_REQUIRED = [
|
|
8
|
+
['category', 'implementation category'],
|
|
9
|
+
['complexity', 'extraction complexity'],
|
|
10
|
+
['agreedDeliveryAt', 'delivery time agreed with the user'],
|
|
11
|
+
['sourceSystem', 'source system'],
|
|
12
|
+
['needsDownload', 'whether the data is downloaded'],
|
|
13
|
+
['feedbackNote', 'feedback note'],
|
|
14
|
+
['managerId', 'extraction manager'],
|
|
15
|
+
['confirmerId', 'business confirmer'],
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* One extraction task of a data usage request. Its approval has no
|
|
19
|
+
* requirements, so it is processed once and submitted, or voided by the
|
|
20
|
+
* acceptor.
|
|
21
|
+
*/
|
|
22
|
+
export const extractionLifecycle = defineLifecycle({
|
|
23
|
+
name: 'extractions',
|
|
24
|
+
collection: COLLECTIONS.extractions,
|
|
25
|
+
initial: 'pending',
|
|
26
|
+
states: [
|
|
27
|
+
'pending',
|
|
28
|
+
{ name: 'completed', final: true },
|
|
29
|
+
{ name: 'voided', final: true },
|
|
30
|
+
],
|
|
31
|
+
transitions: {
|
|
32
|
+
submit: {
|
|
33
|
+
title: '提交反馈',
|
|
34
|
+
from: 'pending',
|
|
35
|
+
to: 'completed',
|
|
36
|
+
guard: ({ record, actor }) => people(record.executorIds).includes(actor.id) ||
|
|
37
|
+
actor.id === DATA_REQUEST_ROLES.acceptor,
|
|
38
|
+
set: ({ record }) => {
|
|
39
|
+
const missing = EXTRACTION_REQUIRED.filter(([field]) => record[field] === null ||
|
|
40
|
+
record[field] === undefined ||
|
|
41
|
+
record[field] === '').map(([, label]) => label);
|
|
42
|
+
// Unfilled fields are the task's state: 400 FAILED_PRECONDITION.
|
|
43
|
+
if (missing.length)
|
|
44
|
+
throw new LifecycleError('INVALID_STATE', `Fill in before submitting: ${missing.join(', ')}.`);
|
|
45
|
+
return {};
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
void: {
|
|
49
|
+
title: '作废',
|
|
50
|
+
from: 'pending',
|
|
51
|
+
to: 'voided',
|
|
52
|
+
guard: ({ actor }) => actor.id === DATA_REQUEST_ROLES.acceptor,
|
|
53
|
+
validate: (input) => typeof input.reason === 'string' && input.reason.trim()
|
|
54
|
+
? null
|
|
55
|
+
: 'Give a reason for voiding the task.',
|
|
56
|
+
set: ({ input }) => ({ voidReason: text(input.reason) }),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction.js","sourceRoot":"","sources":["../../../server/lifecycles/extraction.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,GAGf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAe5C,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAA2C;IACzE,CAAC,UAAU,EAAE,yBAAyB,CAAC;IACvC,CAAC,YAAY,EAAE,uBAAuB,CAAC;IACvC,CAAC,kBAAkB,EAAE,oCAAoC,CAAC;IAC1D,CAAC,cAAc,EAAE,eAAe,CAAC;IACjC,CAAC,eAAe,EAAE,gCAAgC,CAAC;IACnD,CAAC,cAAc,EAAE,eAAe,CAAC;IACjC,CAAC,WAAW,EAAE,oBAAoB,CAAC;IACnC,CAAC,aAAa,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,eAAe,CAAkB;IAC/B,IAAI,EAAE,aAAa;IACnB,UAAU,EAAE,WAAW,CAAC,WAAW;IACnC,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE;QACN,SAAS;QACT,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE;QAClC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;KAChC;IACD,WAAW,EAAE;QACX,MAAM,EAAE;YACN,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAC3B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7C,KAAK,CAAC,EAAE,KAAK,kBAAkB,CAAC,QAAQ;YAC1C,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;gBAClB,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,CACxC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CACV,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI;oBACtB,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS;oBAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CACvB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC5B,iEAAiE;gBACjE,IAAI,OAAO,CAAC,MAAM;oBAChB,MAAM,IAAI,cAAc,CACtB,eAAe,EACf,8BAA8B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACpD,CAAC;gBACJ,OAAO,EAAE,CAAC;YACZ,CAAC;SACF;QACD,IAAI,EAAE;YACJ,KAAK,EAAE,IAAI;YACX,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,QAAQ;YACZ,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,kBAAkB,CAAC,QAAQ;YAC9D,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;gBACrD,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,qCAAqC;YAC3C,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;SACzD;KACF;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type EffectDefinition, type Lifecycle, type LifecycleRecord } from '@nocobase/lifecycle';
|
|
2
|
+
import type { OfficeServices } from './data-request.js';
|
|
3
|
+
export type IncomingState = 'draft' | 'headReview' | 'leaderReview' | 'dispatching' | 'closed';
|
|
4
|
+
export interface Incoming extends LifecycleRecord {
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly registrarId: string;
|
|
7
|
+
readonly officeHeadId: string;
|
|
8
|
+
readonly officeLeaderId: string;
|
|
9
|
+
readonly status: IncomingState;
|
|
10
|
+
}
|
|
11
|
+
export interface IncomingTypes {
|
|
12
|
+
record: Incoming;
|
|
13
|
+
state: IncomingState;
|
|
14
|
+
services: OfficeServices;
|
|
15
|
+
}
|
|
16
|
+
export declare const INCOMING_REQUIRED: readonly (readonly [string, string])[];
|
|
17
|
+
/** Each pending department row becomes a task; its people are reminded once. */
|
|
18
|
+
export declare const dispatchClerks: EffectDefinition<IncomingTypes>;
|
|
19
|
+
/** Pending management rows are forwarded; their members are reminded once. */
|
|
20
|
+
export declare const forwardManagement: EffectDefinition<IncomingTypes>;
|
|
21
|
+
/**
|
|
22
|
+
* An incoming document: the office records it, its head and its leader
|
|
23
|
+
* approve it, and its registrar distributes it to departments. Re-approval
|
|
24
|
+
* sends it back to the head; reminders already sent are not sent again.
|
|
25
|
+
*/
|
|
26
|
+
export declare const incomingLifecycle: Lifecycle<IncomingTypes>;
|
|
27
|
+
//# sourceMappingURL=incoming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incoming.d.ts","sourceRoot":"","sources":["../../../server/lifecycles/incoming.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,MAAM,aAAa,GACvB,OAAO,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,QAAS,SAAQ,eAAe;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAID,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAUnE,CAAC;AAcF,gFAAgF;AAChF,eAAO,MAAM,cAAc,EAAE,gBAAgB,CAAC,aAAa,CAsBvD,CAAC;AAEL,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,CAAC,aAAa,CA8C1D,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,aAAa,CAuFnD,CAAC"}
|