@things-factory/work-shift 10.1.33 → 10.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/pages/work-shift.d.ts +18 -102
- package/dist-client/pages/work-shift.js +165 -781
- package/dist-client/pages/work-shift.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/work-shift-range.d.ts +25 -9
- package/dist-server/controllers/work-shift-range.js +49 -196
- package/dist-server/controllers/work-shift-range.js.map +1 -1
- package/dist-server/controllers/work-shift-schedule.d.ts +2 -0
- package/dist-server/controllers/work-shift-schedule.js +9 -18
- package/dist-server/controllers/work-shift-schedule.js.map +1 -1
- package/dist-server/service/index.d.ts +5 -2
- package/dist-server/service/index.js +3 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/work-shift/index.d.ts +4 -4
- package/dist-server/service/work-shift/index.js +4 -3
- package/dist-server/service/work-shift/index.js.map +1 -1
- package/dist-server/service/work-shift/shift-occurrence.d.ts +19 -0
- package/dist-server/service/work-shift/shift-occurrence.js +34 -0
- package/dist-server/service/work-shift/shift-occurrence.js.map +1 -0
- package/dist-server/service/work-shift/work-shift-arrangement.d.ts +10 -0
- package/dist-server/service/work-shift/work-shift-arrangement.js +40 -0
- package/dist-server/service/work-shift/work-shift-arrangement.js.map +1 -0
- package/dist-server/service/work-shift/work-shift-content.d.ts +15 -0
- package/dist-server/service/work-shift/work-shift-content.js +55 -0
- package/dist-server/service/work-shift/work-shift-content.js.map +1 -0
- package/dist-server/service/work-shift/work-shift-lifecycle-resolver.d.ts +60 -0
- package/dist-server/service/work-shift/work-shift-lifecycle-resolver.js +77 -0
- package/dist-server/service/work-shift/work-shift-lifecycle-resolver.js.map +1 -0
- package/dist-server/service/work-shift/work-shift-lifecycle.d.ts +130 -0
- package/dist-server/service/work-shift/work-shift-lifecycle.js +508 -0
- package/dist-server/service/work-shift/work-shift-lifecycle.js.map +1 -0
- package/dist-server/service/work-shift/work-shift-mutation.js +9 -42
- package/dist-server/service/work-shift/work-shift-mutation.js.map +1 -1
- package/dist-server/service/work-shift/work-shift-query.js +30 -15
- package/dist-server/service/work-shift/work-shift-query.js.map +1 -1
- package/dist-server/service/work-shift/work-shift-revision-service.d.ts +29 -65
- package/dist-server/service/work-shift/work-shift-revision-service.js +67 -167
- package/dist-server/service/work-shift/work-shift-revision-service.js.map +1 -1
- package/dist-server/service/work-shift/work-shift-revision.d.ts +78 -62
- package/dist-server/service/work-shift/work-shift-revision.js +303 -82
- package/dist-server/service/work-shift/work-shift-revision.js.map +1 -1
- package/dist-server/service/work-shift/work-shift-type.d.ts +0 -5
- package/dist-server/service/work-shift/work-shift-type.js +1 -16
- package/dist-server/service/work-shift/work-shift-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/page/work-shift.ko.md +19 -3
- package/helps/page/work-shift.md +17 -9
- package/package.json +8 -5
- package/dist-server/service/work-shift/work-shift-revision-query.d.ts +0 -20
- package/dist-server/service/work-shift/work-shift-revision-query.js +0 -74
- package/dist-server/service/work-shift/work-shift-revision-query.js.map +0 -1
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { Domain } from '@things-factory/shell';
|
|
2
|
-
|
|
3
|
-
export declare function getDateRangeForWorkShift(domain: Domain, workDate: string, workShiftName: string, options?: {
|
|
2
|
+
export declare function getWorkDateAndShift(domain: Domain, at: Date, options?: {
|
|
4
3
|
timezone?: string;
|
|
5
4
|
format?: string;
|
|
6
|
-
}): Promise<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
}): Promise<{
|
|
6
|
+
workDate: string;
|
|
7
|
+
workShift: string;
|
|
8
|
+
shiftRange: Date[];
|
|
9
|
+
dateRange: Date[];
|
|
10
|
+
} | {
|
|
11
|
+
workDate: string;
|
|
12
|
+
workShift: string;
|
|
13
|
+
dateRange: Date[];
|
|
14
|
+
shiftRange?: undefined;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function getDateRangeForWorkShift(domain: Domain, workDate: string, name: string, _options?: any): Promise<Date[]>;
|
|
17
|
+
export declare function getDateRangeForWorkDate(domain: Domain, workDate: string, _options?: any): Promise<Date[]>;
|
|
18
|
+
export declare function getLatestWorkDateAndShift(domain: Domain, at: Date, options?: any): Promise<{
|
|
19
|
+
workDate: string;
|
|
20
|
+
workShift: string;
|
|
21
|
+
shiftRange: Date[];
|
|
22
|
+
dateRange: Date[];
|
|
23
|
+
} | {
|
|
24
|
+
workDate: string;
|
|
25
|
+
workShift: string;
|
|
26
|
+
dateRange: Date[];
|
|
27
|
+
shiftRange?: undefined;
|
|
28
|
+
}>;
|
|
@@ -1,212 +1,65 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getWorkDateAndShift = getWorkDateAndShift;
|
|
3
4
|
exports.getDateRangeForWorkShift = getDateRangeForWorkShift;
|
|
4
5
|
exports.getDateRangeForWorkDate = getDateRangeForWorkDate;
|
|
5
|
-
exports.getWorkDateAndShift = getWorkDateAndShift;
|
|
6
6
|
exports.getLatestWorkDateAndShift = getLatestWorkDateAndShift;
|
|
7
7
|
const tslib_1 = require("tslib");
|
|
8
8
|
const moment_timezone_1 = tslib_1.__importDefault(require("moment-timezone"));
|
|
9
|
-
const env_1 = require("@things-factory/env");
|
|
10
9
|
const shell_1 = require("@things-factory/shell");
|
|
11
|
-
const
|
|
10
|
+
const work_shift_arrangement_1 = require("../service/work-shift/work-shift-arrangement");
|
|
11
|
+
const work_shift_revision_1 = require("../service/work-shift/work-shift-revision");
|
|
12
12
|
const work_shift_revision_service_1 = require("../service/work-shift/work-shift-revision-service");
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return (found?.shifts ?? []);
|
|
13
|
+
const work_shift_lifecycle_1 = require("../service/work-shift/work-shift-lifecycle");
|
|
14
|
+
const shift_occurrence_1 = require("../service/work-shift/shift-occurrence");
|
|
15
|
+
async function getWorkDateAndShift(domain, at, options) {
|
|
16
|
+
const selected = await (0, work_shift_revision_service_1.shiftsInForceAt)((0, shell_1.getRepository)(work_shift_arrangement_1.WorkShiftArrangement).manager, domain, at);
|
|
17
|
+
const zone = selected?.timezone ?? domain.timezone ?? 'UTC';
|
|
18
|
+
if (selected && options?.timezone && options.timezone !== zone)
|
|
19
|
+
throw new shell_1.Refusal('SHIFT_TIMEZONE_MISMATCH', {}, 'Use the published arrangement time zone.');
|
|
20
|
+
const info = (0, shift_occurrence_1.shiftInfoAt)(selected?.shifts ?? [], zone, at, selected?.from, selected?.to);
|
|
21
|
+
if (options?.format)
|
|
22
|
+
info.workDate = (0, moment_timezone_1.default)(info.workDate, 'YYYY-MM-DD').format(options.format);
|
|
23
|
+
return info;
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.
|
|
42
|
-
|
|
43
|
-
return [from, to];
|
|
25
|
+
/** A work date can cross a publication boundary; clip each signed revision to its actual interval. */
|
|
26
|
+
async function windowsForDate(domain, workDate) {
|
|
27
|
+
const m = (0, shell_1.getRepository)(work_shift_arrangement_1.WorkShiftArrangement).manager;
|
|
28
|
+
const root = await m.findOneBy(work_shift_arrangement_1.WorkShiftArrangement, { domain: { id: domain.id } });
|
|
29
|
+
if (!root?.planGeneration)
|
|
30
|
+
return [];
|
|
31
|
+
const plan = await m.findOneByOrFail(work_shift_revision_1.WorkShiftPlan, { domain: { id: domain.id }, arrangement: { id: root.id }, generation: root.planGeneration });
|
|
32
|
+
const segments = await m.find(work_shift_revision_1.WorkShiftSegment, { where: { plan: { id: plan.id }, domain: { id: domain.id } }, relations: { revision: true } });
|
|
33
|
+
return segments.flatMap(segment => {
|
|
34
|
+
const revision = segment.revision;
|
|
35
|
+
if (revision.contentHash !== (0, work_shift_lifecycle_1.workShiftSubmissionHash)(revision))
|
|
36
|
+
throw new shell_1.Refusal('REVISION_INTEGRITY_FAILURE', {}, 'The signed arrangement is invalid.');
|
|
37
|
+
return revision.shifts.map(s => (0, shift_occurrence_1.shiftOccurrence)(s, workDate, revision.timezone)).filter(Boolean).map(w => ({
|
|
38
|
+
...w, from: new Date(Math.max(w.from.getTime(), segment.validFrom.getTime())),
|
|
39
|
+
to: new Date(Math.min(w.to.getTime(), segment.validTo?.getTime() ?? Infinity))
|
|
40
|
+
})).filter(w => w.to > w.from);
|
|
41
|
+
}).sort((a, b) => a.from.getTime() - b.from.getTime());
|
|
44
42
|
}
|
|
45
|
-
async function
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
var beginDate;
|
|
49
|
-
var endDate;
|
|
50
|
-
/* 1. 그 조업일에 쓰던 편성을 가져온다 — 지금 편성이 아닐 수 있다. */
|
|
51
|
-
const workShifts = await shiftsAt(domain, moment_timezone_1.default.tz(workDate, timezone).toDate());
|
|
52
|
-
/* 2. get date-time for every work-shift */
|
|
53
|
-
if (workShifts && workShifts.length > 0) {
|
|
54
|
-
const theDay = moment_timezone_1.default.tz(workDate, timezone);
|
|
55
|
-
for (let j = 0; j < workShifts.length; j++) {
|
|
56
|
-
const { name, fromDate, fromTime, toDate, toTime } = workShifts[j];
|
|
57
|
-
const convertedFromDate = theDay.clone().add(fromDate, 'day');
|
|
58
|
-
const convertedToDate = theDay.clone().add(toDate, 'day');
|
|
59
|
-
const from = moment_timezone_1.default
|
|
60
|
-
.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)
|
|
61
|
-
.toDate();
|
|
62
|
-
const to = moment_timezone_1.default
|
|
63
|
-
.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)
|
|
64
|
-
.toDate();
|
|
65
|
-
if (!beginDate) {
|
|
66
|
-
beginDate = from;
|
|
67
|
-
}
|
|
68
|
-
endDate = to;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
/* 3. in case there are no work-shift, just give date and default shift '' */
|
|
75
|
-
return [beginDate, endDate];
|
|
43
|
+
async function getDateRangeForWorkShift(domain, workDate, name, _options) {
|
|
44
|
+
const rows = (await windowsForDate(domain, workDate)).filter(w => w.name === name);
|
|
45
|
+
return rows.length ? [rows[0].from, rows[rows.length - 1].to] : undefined;
|
|
76
46
|
}
|
|
77
|
-
async function
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
const givenDate = (0, moment_timezone_1.default)(dateTime).tz(timezone);
|
|
81
|
-
/* 1. 그 시각에 쓰던 편성을 가져온다 — 바뀌기 전의 시각이면 지금 편성이 아니다. */
|
|
82
|
-
const workShifts = await shiftsAt(domain, dateTime);
|
|
83
|
-
/* 2. compare given date-time to every work-shift */
|
|
84
|
-
const theDay = givenDate.clone().startOf('day');
|
|
85
|
-
const theDayBefore = theDay.clone().subtract(1, 'day');
|
|
86
|
-
const theDayAfter = theDay.clone().add(1, 'day');
|
|
87
|
-
if (workShifts && workShifts.length > 0) {
|
|
88
|
-
const days = [theDayBefore, theDay, theDayAfter];
|
|
89
|
-
let dateBegin, dateEnd;
|
|
90
|
-
for (let i = 0; i < days.length; i++) {
|
|
91
|
-
const day = days[i];
|
|
92
|
-
dateBegin = null;
|
|
93
|
-
for (let j = 0; j < workShifts.length; j++) {
|
|
94
|
-
const { name, fromDate, fromTime, toDate, toTime } = workShifts[j];
|
|
95
|
-
const convertedFromDate = day.clone().add(fromDate, 'day');
|
|
96
|
-
const convertedToDate = day.clone().add(toDate, 'day');
|
|
97
|
-
const from = moment_timezone_1.default.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
98
|
-
const to = moment_timezone_1.default.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
99
|
-
dateBegin = dateBegin || from;
|
|
100
|
-
dateEnd = from.clone().add(1, 'day');
|
|
101
|
-
if (dateTime >= from.toDate() && to.toDate() > dateTime) {
|
|
102
|
-
return {
|
|
103
|
-
workDate: (0, moment_timezone_1.default)(day).format(format),
|
|
104
|
-
workShift: name,
|
|
105
|
-
dateRange: [dateBegin.toDate(), dateEnd.toDate()],
|
|
106
|
-
shiftRange: [from.toDate(), to.toDate()]
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
/*
|
|
112
|
-
* **교대 시간 밖이다 — 정상이다.**
|
|
113
|
-
*
|
|
114
|
-
* 이 자리는 `logger.error(new Error('shift not found'))` 였고, 던지지 않고 아래에서 정상
|
|
115
|
-
* 반환했다. 「지금은 교대 시간이 아니다」는 밤마다 참이므로, 몇 초마다 스택 트레이스가
|
|
116
|
-
* error 레벨로 쌓였다.
|
|
117
|
-
*
|
|
118
|
-
* plant 레인이 그 로그를 보고 「화면이 터진다」고 사용자님께 잘못 보고했다(2026-09-08).
|
|
119
|
-
* 그쪽 분류(`between-shifts`)와 화면은 처음부터 정상이었다.
|
|
120
|
-
*
|
|
121
|
-
* **정상 상태가 error 로 찍히면 사람이 error 를 안 보게 되고, 잘못 읽게도 된다.** 뒤엣것이
|
|
122
|
-
* 실제로 일어난 쪽이다 — `new Error(...)` 가 스택을 담아 찍으니 던진 것처럼 보인다.
|
|
123
|
-
* 부르는 쪽은 `workShift: ''` 로 그 사실을 이미 받는다 — 로그가 그 위에 더 말할 것이 없다.
|
|
124
|
-
*/
|
|
125
|
-
env_1.logger.debug(`work-shift: ${dateTime} is outside every declared shift — returning an empty shift`);
|
|
126
|
-
}
|
|
127
|
-
/* 3. in case there are no work-shift, just give date and default shift '' */
|
|
128
|
-
return {
|
|
129
|
-
workDate: givenDate.format(format),
|
|
130
|
-
workShift: '',
|
|
131
|
-
dateRange: [theDay.toDate(), theDayAfter.toDate()]
|
|
132
|
-
};
|
|
47
|
+
async function getDateRangeForWorkDate(domain, workDate, _options) {
|
|
48
|
+
const rows = await windowsForDate(domain, workDate);
|
|
49
|
+
return rows.length ? [rows[0].from, new Date(Math.max(...rows.map(w => w.to.getTime())))] : undefined;
|
|
133
50
|
}
|
|
134
|
-
async function getLatestWorkDateAndShift(domain,
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const days = [theDayBefore, theDay, theDayAfter];
|
|
146
|
-
let dateBegin, dateEnd;
|
|
147
|
-
for (let i = 0; i < days.length; i++) {
|
|
148
|
-
const day = days[i];
|
|
149
|
-
dateBegin = null;
|
|
150
|
-
for (let j = 0; j < workShifts.length; j++) {
|
|
151
|
-
const { name, fromDate, fromTime, toDate, toTime } = workShifts[j];
|
|
152
|
-
const convertedFromDate = day.clone().add(fromDate, 'day');
|
|
153
|
-
const convertedToDate = day.clone().add(toDate, 'day');
|
|
154
|
-
const from = moment_timezone_1.default.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
155
|
-
const to = moment_timezone_1.default.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
156
|
-
dateBegin = dateBegin || from;
|
|
157
|
-
dateEnd = from.clone().add(1, 'day');
|
|
158
|
-
if (dateTime < from.toDate()) {
|
|
159
|
-
if (j > 0) {
|
|
160
|
-
const { name, fromDate, fromTime, toDate, toTime } = workShifts[j - 1];
|
|
161
|
-
const from = moment_timezone_1.default.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
162
|
-
const to = moment_timezone_1.default.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
163
|
-
return {
|
|
164
|
-
workDate: (0, moment_timezone_1.default)(day).format(format),
|
|
165
|
-
workShift: name,
|
|
166
|
-
dateRange: [dateBegin.toDate(), dateEnd.toDate()],
|
|
167
|
-
shiftRange: [from.toDate(), to.toDate()]
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
else if (i > 0) {
|
|
171
|
-
const { name, fromDate, fromTime, toDate, toTime } = workShifts[0];
|
|
172
|
-
const convertedFromDate = days[i - 1].clone().add(fromDate, 'day');
|
|
173
|
-
const convertedToDate = days[i - 1].clone().add(toDate, 'day');
|
|
174
|
-
const from = moment_timezone_1.default.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
175
|
-
const to = moment_timezone_1.default.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone);
|
|
176
|
-
return {
|
|
177
|
-
workDate: (0, moment_timezone_1.default)(day).format(format),
|
|
178
|
-
workShift: name,
|
|
179
|
-
dateRange: [dateBegin.clone().subtract(1, 'day').toDate(), dateBegin.toDate()],
|
|
180
|
-
shiftRange: [from.toDate(), to.toDate()]
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/*
|
|
190
|
-
* **교대 시간 밖이다 — 정상이다.**
|
|
191
|
-
*
|
|
192
|
-
* 이 자리는 `logger.error(new Error('shift not found'))` 였고, 던지지 않고 아래에서 정상
|
|
193
|
-
* 반환했다. 「지금은 교대 시간이 아니다」는 밤마다 참이므로, 몇 초마다 스택 트레이스가
|
|
194
|
-
* error 레벨로 쌓였다.
|
|
195
|
-
*
|
|
196
|
-
* plant 레인이 그 로그를 보고 「화면이 터진다」고 사용자님께 잘못 보고했다(2026-09-08).
|
|
197
|
-
* 그쪽 분류(`between-shifts`)와 화면은 처음부터 정상이었다.
|
|
198
|
-
*
|
|
199
|
-
* **정상 상태가 error 로 찍히면 사람이 error 를 안 보게 되고, 잘못 읽게도 된다.** 뒤엣것이
|
|
200
|
-
* 실제로 일어난 쪽이다 — `new Error(...)` 가 스택을 담아 찍으니 던진 것처럼 보인다.
|
|
201
|
-
* 부르는 쪽은 `workShift: ''` 로 그 사실을 이미 받는다 — 로그가 그 위에 더 말할 것이 없다.
|
|
202
|
-
*/
|
|
203
|
-
env_1.logger.debug(`work-shift: ${dateTime} is outside every declared shift — returning an empty shift`);
|
|
51
|
+
async function getLatestWorkDateAndShift(domain, at, options) {
|
|
52
|
+
const current = await getWorkDateAndShift(domain, at, options);
|
|
53
|
+
if (current.workShift)
|
|
54
|
+
return current;
|
|
55
|
+
const day = (0, moment_timezone_1.default)(at).tz(domain.timezone || 'UTC');
|
|
56
|
+
for (let offset = 0; offset < 8; offset++) {
|
|
57
|
+
const workDate = day.clone().subtract(offset, 'day').format('YYYY-MM-DD');
|
|
58
|
+
const rows = (await windowsForDate(domain, workDate)).filter(w => w.from <= at).sort((a, b) => b.from.getTime() - a.from.getTime());
|
|
59
|
+
if (rows.length)
|
|
60
|
+
return { workDate, workShift: rows[0].name, shiftRange: [rows[0].from, rows[0].to],
|
|
61
|
+
dateRange: await getDateRangeForWorkDate(domain, workDate) };
|
|
204
62
|
}
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
workDate: givenDate.clone().subtract(1, 'day').format(format),
|
|
208
|
-
workShift: '',
|
|
209
|
-
dateRange: [theDayBefore.toDate(), theDay.toDate()]
|
|
210
|
-
};
|
|
63
|
+
return current;
|
|
211
64
|
}
|
|
212
65
|
//# sourceMappingURL=work-shift-range.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-shift-range.js","sourceRoot":"","sources":["../../server/controllers/work-shift-range.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\n\nimport { logger } from '@things-factory/env'\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { WorkShift } from '../service/work-shift/work-shift'\nimport { WorkShiftInfo } from '../service/work-shift/work-shift-type'\nimport { shiftsInForceAt } from '../service/work-shift/work-shift-revision-service'\n\n/**\n * 그 시각에 쓰던 교대 — **지금 편성이 아닐 수 있다.**\n *\n * 편성이 바뀌기 전의 시각을 지금 편성으로 읽으면, 그 시각의 사실이 있지도 않았던 교대 이름으로 나온다.\n * 공장이 2교대에서 3교대로 바꾸는 날 지난 석 달의 실적이 통째로 다시 이름 붙는 것이 그것이다.\n *\n * **이력보다 앞선 시각은 빈 목록이다.** 그때 무엇을 쓰고 있었는지 이 시스템은 모른다 — 지금 편성으로\n * 대신하지 않는다.\n */\nasync function shiftsAt(domain: Domain, at: Date): Promise<Pick<WorkShift, 'name' | 'fromDate' | 'fromTime' | 'toDate' | 'toTime'>[]> {\n const found = await shiftsInForceAt(getRepository(WorkShift).manager, domain, at)\n\n return (found?.shifts ?? []) as Pick<WorkShift, 'name' | 'fromDate' | 'fromTime' | 'toDate' | 'toTime'>[]\n}\n\nexport async function getDateRangeForWorkShift(\n domain: Domain,\n workDate: string,\n workShiftName: string,\n options?: { timezone?: string; format?: string }\n): Promise<Date[]> {\n const dateOptions = { timezone: domain.timezone || 'UTC', format: 'YYYY-MM-DD', ...options }\n const { timezone, format } = dateOptions\n\n /* 그 조업일에 쓰던 편성에서 찾는다 — 지금 편성에는 없는 이름일 수 있다. */\n const asOf = moment.tz(workDate, timezone).toDate()\n const workShift = (await shiftsAt(domain, asOf)).find(shift => shift.name === workShiftName)\n\n if (!workShift) {\n return\n }\n const theDay = moment.tz(workDate, timezone)\n const { name, fromDate, fromTime, toDate, toTime } = workShift\n\n const convertedFromDate = theDay.clone().add(fromDate, 'day')\n const convertedToDate = theDay.clone().add(toDate, 'day')\n const from = moment\n .tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n .toDate()\n const to = moment.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone).toDate()\n\n return [from, to]\n}\n\nexport async function getDateRangeForWorkDate(\n domain: Domain,\n workDate: string,\n options?: { timezone?: string; format?: string }\n) {\n const dateOptions = { timezone: domain.timezone || 'UTC', format: 'YYYY-MM-DD', ...options }\n const { timezone, format } = dateOptions\n\n var beginDate\n var endDate\n\n /* 1. 그 조업일에 쓰던 편성을 가져온다 — 지금 편성이 아닐 수 있다. */\n const workShifts = await shiftsAt(domain, moment.tz(workDate, timezone).toDate())\n\n /* 2. get date-time for every work-shift */\n if (workShifts && workShifts.length > 0) {\n const theDay = moment.tz(workDate, timezone)\n\n for (let j = 0; j < workShifts.length; j++) {\n const { name, fromDate, fromTime, toDate, toTime } = workShifts[j]\n\n const convertedFromDate = theDay.clone().add(fromDate, 'day')\n const convertedToDate = theDay.clone().add(toDate, 'day')\n const from = moment\n .tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n .toDate()\n const to = moment\n .tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n .toDate()\n\n if (!beginDate) {\n beginDate = from\n }\n\n endDate = to\n }\n } else {\n return\n }\n\n /* 3. in case there are no work-shift, just give date and default shift '' */\n return [beginDate, endDate]\n}\n\nexport async function getWorkDateAndShift(domain: Domain, dateTime: Date, options?: any): Promise<WorkShiftInfo> {\n const dateOptions = { timezone: domain.timezone || 'UTC', format: 'YYYY-MM-DD', ...options }\n const { timezone, format } = dateOptions\n\n const givenDate = moment(dateTime).tz(timezone)\n /* 1. 그 시각에 쓰던 편성을 가져온다 — 바뀌기 전의 시각이면 지금 편성이 아니다. */\n const workShifts = await shiftsAt(domain, dateTime)\n\n /* 2. compare given date-time to every work-shift */\n const theDay = givenDate.clone().startOf('day')\n const theDayBefore = theDay.clone().subtract(1, 'day')\n const theDayAfter = theDay.clone().add(1, 'day')\n\n if (workShifts && workShifts.length > 0) {\n const days = [theDayBefore, theDay, theDayAfter]\n let dateBegin, dateEnd\n\n for (let i = 0; i < days.length; i++) {\n const day = days[i]\n dateBegin = null\n\n for (let j = 0; j < workShifts.length; j++) {\n const { name, fromDate, fromTime, toDate, toTime } = workShifts[j]\n\n const convertedFromDate = day.clone().add(fromDate, 'day')\n const convertedToDate = day.clone().add(toDate, 'day')\n\n const from = moment.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n const to = moment.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n\n dateBegin = dateBegin || from\n dateEnd = from.clone().add(1, 'day')\n\n if (dateTime >= from.toDate() && to.toDate() > dateTime) {\n return {\n workDate: moment(day).format(format),\n workShift: name,\n dateRange: [dateBegin.toDate(), dateEnd.toDate()],\n shiftRange: [from.toDate(), to.toDate()]\n }\n }\n }\n }\n\n /*\n * **교대 시간 밖이다 — 정상이다.**\n *\n * 이 자리는 `logger.error(new Error('shift not found'))` 였고, 던지지 않고 아래에서 정상\n * 반환했다. 「지금은 교대 시간이 아니다」는 밤마다 참이므로, 몇 초마다 스택 트레이스가\n * error 레벨로 쌓였다.\n *\n * plant 레인이 그 로그를 보고 「화면이 터진다」고 사용자님께 잘못 보고했다(2026-09-08).\n * 그쪽 분류(`between-shifts`)와 화면은 처음부터 정상이었다.\n *\n * **정상 상태가 error 로 찍히면 사람이 error 를 안 보게 되고, 잘못 읽게도 된다.** 뒤엣것이\n * 실제로 일어난 쪽이다 — `new Error(...)` 가 스택을 담아 찍으니 던진 것처럼 보인다.\n * 부르는 쪽은 `workShift: ''` 로 그 사실을 이미 받는다 — 로그가 그 위에 더 말할 것이 없다.\n */\n logger.debug(`work-shift: ${dateTime} is outside every declared shift — returning an empty shift`)\n }\n\n /* 3. in case there are no work-shift, just give date and default shift '' */\n return {\n workDate: givenDate.format(format),\n workShift: '',\n dateRange: [theDay.toDate(), theDayAfter.toDate()]\n }\n}\n\nexport async function getLatestWorkDateAndShift(domain: Domain, dateTime: Date, options?: any): Promise<WorkShiftInfo> {\n const dateOptions = { timezone: domain.timezone || 'UTC', format: 'YYYY-MM-DD', ...options }\n const { timezone, format } = dateOptions\n\n const givenDate = moment(dateTime).tz(timezone)\n\n /* 1. 그 시각에 쓰던 편성을 가져온다 — 바뀌기 전의 시각이면 지금 편성이 아니다. */\n const workShifts = await shiftsAt(domain, dateTime)\n\n /* 2. compare given date-time to every work-shift */\n const theDay = givenDate.clone().startOf('day')\n const theDayBefore = theDay.clone().subtract(1, 'day')\n const theDayAfter = theDay.clone().add(1, 'day')\n\n if (workShifts && workShifts.length > 0) {\n const days = [theDayBefore, theDay, theDayAfter]\n let dateBegin, dateEnd\n\n for (let i = 0; i < days.length; i++) {\n const day = days[i]\n dateBegin = null\n\n for (let j = 0; j < workShifts.length; j++) {\n const { name, fromDate, fromTime, toDate, toTime } = workShifts[j]\n\n const convertedFromDate = day.clone().add(fromDate, 'day')\n const convertedToDate = day.clone().add(toDate, 'day')\n\n const from = moment.tz(`${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n const to = moment.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n\n dateBegin = dateBegin || from\n dateEnd = from.clone().add(1, 'day')\n\n if (dateTime < from.toDate()) {\n if (j > 0) {\n const { name, fromDate, fromTime, toDate, toTime } = workShifts[j - 1]\n\n const from = moment.tz(\n `${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`,\n 'YYYY-MM-DD HH:mm:ss',\n timezone\n )\n const to = moment.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n\n return {\n workDate: moment(day).format(format),\n workShift: name,\n dateRange: [dateBegin.toDate(), dateEnd.toDate()],\n shiftRange: [from.toDate(), to.toDate()]\n }\n } else if (i > 0) {\n const { name, fromDate, fromTime, toDate, toTime } = workShifts[0]\n\n const convertedFromDate = days[i - 1].clone().add(fromDate, 'day')\n const convertedToDate = days[i - 1].clone().add(toDate, 'day')\n\n const from = moment.tz(\n `${convertedFromDate.format('YYYY-MM-DD')} ${fromTime}`,\n 'YYYY-MM-DD HH:mm:ss',\n timezone\n )\n const to = moment.tz(`${convertedToDate.format('YYYY-MM-DD')} ${toTime}`, 'YYYY-MM-DD HH:mm:ss', timezone)\n\n return {\n workDate: moment(day).format(format),\n workShift: name,\n dateRange: [dateBegin.clone().subtract(1, 'day').toDate(), dateBegin.toDate()],\n shiftRange: [from.toDate(), to.toDate()]\n }\n } else {\n return\n }\n }\n }\n }\n\n /*\n * **교대 시간 밖이다 — 정상이다.**\n *\n * 이 자리는 `logger.error(new Error('shift not found'))` 였고, 던지지 않고 아래에서 정상\n * 반환했다. 「지금은 교대 시간이 아니다」는 밤마다 참이므로, 몇 초마다 스택 트레이스가\n * error 레벨로 쌓였다.\n *\n * plant 레인이 그 로그를 보고 「화면이 터진다」고 사용자님께 잘못 보고했다(2026-09-08).\n * 그쪽 분류(`between-shifts`)와 화면은 처음부터 정상이었다.\n *\n * **정상 상태가 error 로 찍히면 사람이 error 를 안 보게 되고, 잘못 읽게도 된다.** 뒤엣것이\n * 실제로 일어난 쪽이다 — `new Error(...)` 가 스택을 담아 찍으니 던진 것처럼 보인다.\n * 부르는 쪽은 `workShift: ''` 로 그 사실을 이미 받는다 — 로그가 그 위에 더 말할 것이 없다.\n */\n logger.debug(`work-shift: ${dateTime} is outside every declared shift — returning an empty shift`)\n }\n\n /* 3. in case there are no work-shift, just give date and default shift '' */\n return {\n workDate: givenDate.clone().subtract(1, 'day').format(format),\n workShift: '',\n dateRange: [theDayBefore.toDate(), theDay.toDate()]\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"work-shift-range.js","sourceRoot":"","sources":["../../server/controllers/work-shift-range.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { Domain, getRepository, Refusal } from '@things-factory/shell'\nimport { WorkShiftArrangement } from '../service/work-shift/work-shift-arrangement'\nimport { WorkShiftPlan, WorkShiftRevision, WorkShiftSegment } from '../service/work-shift/work-shift-revision'\nimport { shiftsInForceAt } from '../service/work-shift/work-shift-revision-service'\nimport { workShiftSubmissionHash } from '../service/work-shift/work-shift-lifecycle'\nimport { shiftInfoAt, shiftOccurrence } from '../service/work-shift/shift-occurrence'\n\nexport async function getWorkDateAndShift(domain: Domain, at: Date, options?: { timezone?: string; format?: string }) {\n const selected = await shiftsInForceAt(getRepository(WorkShiftArrangement).manager, domain, at)\n const zone = selected?.timezone ?? domain.timezone ?? 'UTC'\n if (selected && options?.timezone && options.timezone !== zone) throw new Refusal('SHIFT_TIMEZONE_MISMATCH', {}, 'Use the published arrangement time zone.')\n const info = shiftInfoAt(selected?.shifts ?? [], zone, at, selected?.from, selected?.to)\n if (options?.format) info.workDate = moment(info.workDate, 'YYYY-MM-DD').format(options.format)\n return info\n}\n\n/** A work date can cross a publication boundary; clip each signed revision to its actual interval. */\nasync function windowsForDate(domain: Domain, workDate: string) {\n const m = getRepository(WorkShiftArrangement).manager\n const root = await m.findOneBy(WorkShiftArrangement, { domain: { id: domain.id } })\n if (!root?.planGeneration) return []\n const plan = await m.findOneByOrFail(WorkShiftPlan, { domain: { id: domain.id }, arrangement: { id: root.id }, generation: root.planGeneration })\n const segments = await m.find(WorkShiftSegment, { where: { plan: { id: plan.id }, domain: { id: domain.id } }, relations: { revision: true } })\n return segments.flatMap(segment => {\n const revision = segment.revision\n if (revision.contentHash !== workShiftSubmissionHash(revision)) throw new Refusal('REVISION_INTEGRITY_FAILURE', {}, 'The signed arrangement is invalid.')\n return revision.shifts.map(s => shiftOccurrence(s, workDate, revision.timezone)).filter(Boolean).map(w => ({\n ...w, from: new Date(Math.max(w.from.getTime(), segment.validFrom.getTime())),\n to: new Date(Math.min(w.to.getTime(), segment.validTo?.getTime() ?? Infinity))\n })).filter(w => w.to > w.from)\n }).sort((a,b) => a.from.getTime() - b.from.getTime())\n}\nexport async function getDateRangeForWorkShift(domain: Domain, workDate: string, name: string, _options?: any): Promise<Date[]> {\n const rows = (await windowsForDate(domain, workDate)).filter(w => w.name === name)\n return rows.length ? [rows[0].from, rows[rows.length - 1].to] : undefined\n}\nexport async function getDateRangeForWorkDate(domain: Domain, workDate: string, _options?: any): Promise<Date[]> {\n const rows = await windowsForDate(domain, workDate)\n return rows.length ? [rows[0].from, new Date(Math.max(...rows.map(w => w.to.getTime())))] : undefined\n}\nexport async function getLatestWorkDateAndShift(domain: Domain, at: Date, options?: any) {\n const current = await getWorkDateAndShift(domain, at, options)\n if (current.workShift) return current\n const day = moment(at).tz(domain.timezone || 'UTC')\n for (let offset = 0; offset < 8; offset++) {\n const workDate = day.clone().subtract(offset, 'day').format('YYYY-MM-DD')\n const rows = (await windowsForDate(domain, workDate)).filter(w => w.from <= at).sort((a,b) => b.from.getTime() - a.from.getTime())\n if (rows.length) return { workDate, workShift: rows[0].name, shiftRange: [rows[0].from, rows[0].to],\n dateRange: await getDateRangeForWorkDate(domain, workDate) }\n }\n return current\n}\n"]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { Domain } from '@things-factory/shell';
|
|
2
2
|
export declare function getSummaryScheduleForWorkShift(domain: Domain): Promise<string>;
|
|
3
3
|
export declare function getSummaryScheduleForWorkDate(domain: Domain): Promise<string>;
|
|
4
|
+
export declare function timePlusThirtyMinutesToCron(time: string): string;
|
|
5
|
+
export declare function getNextHourIn24HourFormat(time: string): string;
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getSummaryScheduleForWorkShift = getSummaryScheduleForWorkShift;
|
|
4
4
|
exports.getSummaryScheduleForWorkDate = getSummaryScheduleForWorkDate;
|
|
5
|
+
exports.timePlusThirtyMinutesToCron = timePlusThirtyMinutesToCron;
|
|
6
|
+
exports.getNextHourIn24HourFormat = getNextHourIn24HourFormat;
|
|
5
7
|
const shell_1 = require("@things-factory/shell");
|
|
6
8
|
const work_shift_1 = require("../service/work-shift/work-shift");
|
|
9
|
+
const work_shift_revision_service_1 = require("../service/work-shift/work-shift-revision-service");
|
|
7
10
|
async function getSummaryScheduleForWorkShift(domain) {
|
|
8
|
-
const workShifts = await (0, shell_1.getRepository)(work_shift_1.WorkShift).
|
|
9
|
-
where: {
|
|
10
|
-
domain: { id: domain.id }
|
|
11
|
-
}
|
|
12
|
-
});
|
|
11
|
+
const workShifts = await (0, work_shift_revision_service_1.effectiveWorkShifts)((0, shell_1.getRepository)(work_shift_1.WorkShift).manager, domain);
|
|
13
12
|
if (!workShifts || workShifts.length == 0) {
|
|
14
13
|
return '';
|
|
15
14
|
}
|
|
@@ -17,19 +16,11 @@ async function getSummaryScheduleForWorkShift(domain) {
|
|
|
17
16
|
.map(workShift => workShift.toTime)
|
|
18
17
|
.map(getNextHourIn24HourFormat)
|
|
19
18
|
.join(',');
|
|
20
|
-
return `10 ${hours} * *
|
|
19
|
+
return `10 ${hours} * * *`;
|
|
21
20
|
}
|
|
22
21
|
async function getSummaryScheduleForWorkDate(domain) {
|
|
23
22
|
/* 1. 도메인의 워크시프트를 모두 가져온다. */
|
|
24
|
-
const workShifts = await (0, shell_1.getRepository)(work_shift_1.WorkShift).
|
|
25
|
-
where: {
|
|
26
|
-
domain: { id: domain.id }
|
|
27
|
-
},
|
|
28
|
-
order: {
|
|
29
|
-
fromDate: 'ASC',
|
|
30
|
-
fromTime: 'ASC'
|
|
31
|
-
}
|
|
32
|
-
});
|
|
23
|
+
const workShifts = await (0, work_shift_revision_service_1.effectiveWorkShifts)((0, shell_1.getRepository)(work_shift_1.WorkShift).manager, domain);
|
|
33
24
|
/* 2. 워크데이의 마지막 시간을 구한 뒤, 그 30분뒤 시간에 매일 수행하는 crontab을 계산한다. */
|
|
34
25
|
if (workShifts && workShifts.length > 0) {
|
|
35
26
|
const { toTime } = workShifts[workShifts.length - 1];
|
|
@@ -47,20 +38,20 @@ function timePlusThirtyMinutesToCron(time) {
|
|
|
47
38
|
.split(':')
|
|
48
39
|
.map(Number);
|
|
49
40
|
// 기준 날짜와 시간 정보를 사용하여 Date 객체를 생성합니다.
|
|
50
|
-
let date = new Date(1970, 0, 1,
|
|
41
|
+
let date = new Date(1970, 0, 1, /AM|PM/i.test(time) ? (hours % 12) + (isPM ? 12 : 0) : hours, minutes);
|
|
51
42
|
// 30분을 추가합니다.
|
|
52
43
|
date.setMinutes(date.getMinutes() + 30);
|
|
53
44
|
// 결과 시간을 얻습니다.
|
|
54
45
|
const resultHours = String(date.getHours()).padStart(2, '0');
|
|
55
46
|
const resultMinutes = String(date.getMinutes()).padStart(2, '0');
|
|
56
47
|
// 결과 시간을 사용하여 crontab 항목을 반환합니다.
|
|
57
|
-
return `${resultMinutes} ${resultHours} * *
|
|
48
|
+
return `${resultMinutes} ${resultHours} * * *`;
|
|
58
49
|
}
|
|
59
50
|
function getNextHourIn24HourFormat(time) {
|
|
60
51
|
const isPM = time.toUpperCase().includes('PM');
|
|
61
52
|
const hours = Number(time.split(':')[0]);
|
|
62
53
|
// 기준 날짜와 시간 정보를 사용하여 Date 객체를 생성합니다.
|
|
63
|
-
let date = new Date(1970, 0, 1,
|
|
54
|
+
let date = new Date(1970, 0, 1, /AM|PM/i.test(time) ? (hours % 12) + (isPM ? 12 : 0) : hours, 0);
|
|
64
55
|
// 시간 값을 1 증가시킵니다.
|
|
65
56
|
date.setHours(date.getHours() + 1);
|
|
66
57
|
// 결과 시간을 얻습니다.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-shift-schedule.js","sourceRoot":"","sources":["../../server/controllers/work-shift-schedule.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"work-shift-schedule.js","sourceRoot":"","sources":["../../server/controllers/work-shift-schedule.ts"],"names":[],"mappings":"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","sourcesContent":["import { Domain, getRepository } from '@things-factory/shell'\n\nimport { WorkShift } from '../service/work-shift/work-shift'\nimport { effectiveWorkShifts } from '../service/work-shift/work-shift-revision-service'\n\nexport async function getSummaryScheduleForWorkShift(domain: Domain): Promise<string> {\n const workShifts = await effectiveWorkShifts(getRepository(WorkShift).manager, domain)\n\n if (!workShifts || workShifts.length == 0) {\n return ''\n }\n\n const hours = workShifts\n .map(workShift => workShift.toTime)\n .map(getNextHourIn24HourFormat)\n .join(',')\n\n return `10 ${hours} * * *`\n}\n\nexport async function getSummaryScheduleForWorkDate(domain: Domain): Promise<string> {\n /* 1. 도메인의 워크시프트를 모두 가져온다. */\n const workShifts = await effectiveWorkShifts(getRepository(WorkShift).manager, domain)\n\n /* 2. 워크데이의 마지막 시간을 구한 뒤, 그 30분뒤 시간에 매일 수행하는 crontab을 계산한다. */\n if (workShifts && workShifts.length > 0) {\n const { toTime } = workShifts[workShifts.length - 1]\n return timePlusThirtyMinutesToCron(toTime)\n } else {\n return\n }\n}\n\nexport function timePlusThirtyMinutesToCron(time: string): string {\n const isPM = time.toUpperCase().includes('PM')\n const [hours, minutes] = time\n .toUpperCase()\n .replace(/(AM|PM)/, '')\n .split(':')\n .map(Number)\n\n // 기준 날짜와 시간 정보를 사용하여 Date 객체를 생성합니다.\n let date = new Date(1970, 0, 1, /AM|PM/i.test(time) ? (hours % 12) + (isPM ? 12 : 0) : hours, minutes)\n\n // 30분을 추가합니다.\n date.setMinutes(date.getMinutes() + 30)\n\n // 결과 시간을 얻습니다.\n const resultHours = String(date.getHours()).padStart(2, '0')\n const resultMinutes = String(date.getMinutes()).padStart(2, '0')\n\n // 결과 시간을 사용하여 crontab 항목을 반환합니다.\n return `${resultMinutes} ${resultHours} * * *`\n}\n\nexport function getNextHourIn24HourFormat(time: string): string {\n const isPM = time.toUpperCase().includes('PM')\n const hours = Number(time.split(':')[0])\n\n // 기준 날짜와 시간 정보를 사용하여 Date 객체를 생성합니다.\n let date = new Date(1970, 0, 1, /AM|PM/i.test(time) ? (hours % 12) + (isPM ? 12 : 0) : hours, 0)\n\n // 시간 값을 1 증가시킵니다.\n date.setHours(date.getHours() + 1)\n\n // 결과 시간을 얻습니다.\n return String(date.getHours()).padStart(2, '0')\n}\n"]}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export * from './work-shift/work-shift';
|
|
2
2
|
export * from './work-shift/work-shift-revision';
|
|
3
3
|
export * from './work-shift/work-shift-revision-service';
|
|
4
|
+
export * from './work-shift/work-shift-lifecycle';
|
|
5
|
+
export * from './work-shift/work-shift-arrangement';
|
|
6
|
+
export * from './work-shift/work-shift-content';
|
|
4
7
|
export * from './work-shift/days-of-week';
|
|
5
|
-
export declare const entities: (typeof import("./work-shift/work-shift-revision").WorkShiftRevision | typeof import("./work-shift/work-shift").WorkShift)[];
|
|
8
|
+
export declare const entities: (typeof import("./work-shift/work-shift-arrangement").WorkShiftArrangement | typeof import("./work-shift/work-shift-revision").WorkShiftRevision | typeof import("./work-shift/work-shift-revision").WorkShiftPlan | typeof import("./work-shift/work-shift-revision").WorkShiftSegment | typeof import("./work-shift/work-shift-revision").WorkShiftBasis | typeof import("./work-shift/work-shift").WorkShift)[];
|
|
6
9
|
export declare const schema: {
|
|
7
|
-
resolverClasses: (typeof import("./work-shift/work-shift-
|
|
10
|
+
resolverClasses: (typeof import("./work-shift/work-shift-query").DomainWorkShiftQuery | typeof import("./work-shift/work-shift-query").WorkShiftQuery | typeof import("./work-shift/work-shift-mutation").WorkShiftMutation | typeof import("./work-shift/work-shift-lifecycle-resolver").WorkShiftLifecycleResolver)[];
|
|
8
11
|
};
|
|
@@ -6,6 +6,9 @@ const tslib_1 = require("tslib");
|
|
|
6
6
|
tslib_1.__exportStar(require("./work-shift/work-shift"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./work-shift/work-shift-revision"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./work-shift/work-shift-revision-service"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./work-shift/work-shift-lifecycle"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./work-shift/work-shift-arrangement"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./work-shift/work-shift-content"), exports);
|
|
9
12
|
/*
|
|
10
13
|
* This file names each source file rather than re-exporting the folder barrel, so anything added
|
|
11
14
|
* to that barrel stops at the package boundary unless it is also listed here. `daysOfWeek` is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,kEAAuC;AACvC,2EAAgD;AAChD,mFAAwD;AACxD;;;;;GAKG;AACH,oEAAyC;AAEzC,mCAAmC;AACnC,6CAA6F;AAEhF,QAAA,QAAQ,GAAG;IACtB,cAAc;IACf,GAAG,qBAAiB;CACpB,CAAA;AAGY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACxB,GAAG,sBAAkB;KACpB;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './work-shift/work-shift'\nexport * from './work-shift/work-shift-revision'\nexport * from './work-shift/work-shift-revision-service'\n/*\n * This file names each source file rather than re-exporting the folder barrel, so anything added\n * to that barrel stops at the package boundary unless it is also listed here. `daysOfWeek` is\n * stored as a CSV and every consumer has to parse it, so the parser has to be reachable — a\n * consumer that cannot import it writes its own, and the two disagree quietly.\n */\nexport * from './work-shift/days-of-week'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { entities as WorkShiftEntities, resolvers as WorkShiftResolvers } from './work-shift'\n\nexport const entities = [ \n /* ENTITIES */\n\t...WorkShiftEntities,\n] \n\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n\t\t...WorkShiftResolvers,\n ] \n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,kEAAuC;AACvC,2EAAgD;AAChD,mFAAwD;AACxD,4EAAiD;AACjD,8EAAmD;AACnD,0EAA+C;AAC/C;;;;;GAKG;AACH,oEAAyC;AAEzC,mCAAmC;AACnC,6CAA6F;AAEhF,QAAA,QAAQ,GAAG;IACtB,cAAc;IACf,GAAG,qBAAiB;CACpB,CAAA;AAGY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACxB,GAAG,sBAAkB;KACpB;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './work-shift/work-shift'\nexport * from './work-shift/work-shift-revision'\nexport * from './work-shift/work-shift-revision-service'\nexport * from './work-shift/work-shift-lifecycle'\nexport * from './work-shift/work-shift-arrangement'\nexport * from './work-shift/work-shift-content'\n/*\n * This file names each source file rather than re-exporting the folder barrel, so anything added\n * to that barrel stops at the package boundary unless it is also listed here. `daysOfWeek` is\n * stored as a CSV and every consumer has to parse it, so the parser has to be reachable — a\n * consumer that cannot import it writes its own, and the two disagree quietly.\n */\nexport * from './work-shift/days-of-week'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { entities as WorkShiftEntities, resolvers as WorkShiftResolvers } from './work-shift'\n\nexport const entities = [ \n /* ENTITIES */\n\t...WorkShiftEntities,\n] \n\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n\t\t...WorkShiftResolvers,\n ] \n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DomainWorkShiftQuery, WorkShiftQuery } from './work-shift-query';
|
|
2
2
|
import { WorkShift } from './work-shift';
|
|
3
3
|
import { WorkShiftMutation } from './work-shift-mutation';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { WorkShiftLifecycleResolver } from './work-shift-lifecycle-resolver';
|
|
5
|
+
import { WorkShiftArrangement } from './work-shift-arrangement';
|
|
6
6
|
export * from './days-of-week';
|
|
7
|
-
export declare const entities: (typeof WorkShiftRevision | typeof WorkShift)[];
|
|
8
|
-
export declare const resolvers: (typeof
|
|
7
|
+
export declare const entities: (typeof WorkShiftArrangement | typeof import("./work-shift-revision").WorkShiftRevision | typeof import("./work-shift-revision").WorkShiftPlan | typeof import("./work-shift-revision").WorkShiftSegment | typeof import("./work-shift-revision").WorkShiftBasis | typeof WorkShift)[];
|
|
8
|
+
export declare const resolvers: (typeof DomainWorkShiftQuery | typeof WorkShiftQuery | typeof WorkShiftMutation | typeof WorkShiftLifecycleResolver)[];
|
|
@@ -5,14 +5,15 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const work_shift_query_1 = require("./work-shift-query");
|
|
6
6
|
const work_shift_1 = require("./work-shift");
|
|
7
7
|
const work_shift_mutation_1 = require("./work-shift-mutation");
|
|
8
|
+
const work_shift_lifecycle_resolver_1 = require("./work-shift-lifecycle-resolver");
|
|
8
9
|
const work_shift_revision_1 = require("./work-shift-revision");
|
|
9
|
-
const
|
|
10
|
+
const work_shift_arrangement_1 = require("./work-shift-arrangement");
|
|
10
11
|
/*
|
|
11
12
|
* The weekday rule is exported so consumers read the column through one parser. It is a CSV
|
|
12
13
|
* because array columns are not portable across the five drivers, and a parser written twice
|
|
13
14
|
* disagrees eventually — quietly, since both halves keep computing (§`days-of-week.ts`).
|
|
14
15
|
*/
|
|
15
16
|
tslib_1.__exportStar(require("./days-of-week"), exports);
|
|
16
|
-
exports.entities = [work_shift_1.WorkShift, work_shift_revision_1.
|
|
17
|
-
exports.resolvers = [work_shift_query_1.DomainWorkShiftQuery, work_shift_query_1.WorkShiftQuery, work_shift_mutation_1.WorkShiftMutation,
|
|
17
|
+
exports.entities = [work_shift_1.WorkShift, work_shift_arrangement_1.WorkShiftArrangement, ...work_shift_revision_1.WORK_SHIFT_REVISION_ENTITIES];
|
|
18
|
+
exports.resolvers = [work_shift_query_1.DomainWorkShiftQuery, work_shift_query_1.WorkShiftQuery, work_shift_mutation_1.WorkShiftMutation, work_shift_lifecycle_resolver_1.WorkShiftLifecycleResolver];
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/work-shift/index.ts"],"names":[],"mappings":";;;;AAAA,yDAAyE;AAEzE,6CAAwC;AACxC,+DAAyD;AACzD,+
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/work-shift/index.ts"],"names":[],"mappings":";;;;AAAA,yDAAyE;AAEzE,6CAAwC;AACxC,+DAAyD;AACzD,mFAA4E;AAC5E,+DAAoE;AACpE,qEAA+D;AAE/D;;;;GAIG;AACH,yDAA8B;AAEjB,QAAA,QAAQ,GAAG,CAAC,sBAAS,EAAE,6CAAoB,EAAE,GAAG,kDAA4B,CAAC,CAAA;AAC7E,QAAA,SAAS,GAAG,CAAC,uCAAoB,EAAE,iCAAc,EAAE,uCAAiB,EAAE,0DAA0B,CAAC,CAAA","sourcesContent":["import { DomainWorkShiftQuery, WorkShiftQuery } from './work-shift-query'\n\nimport { WorkShift } from './work-shift'\nimport { WorkShiftMutation } from './work-shift-mutation'\nimport { WorkShiftLifecycleResolver } from './work-shift-lifecycle-resolver'\nimport { WORK_SHIFT_REVISION_ENTITIES } from './work-shift-revision'\nimport { WorkShiftArrangement } from './work-shift-arrangement'\n\n/*\n * The weekday rule is exported so consumers read the column through one parser. It is a CSV\n * because array columns are not portable across the five drivers, and a parser written twice\n * disagrees eventually — quietly, since both halves keep computing (§`days-of-week.ts`).\n */\nexport * from './days-of-week'\n\nexport const entities = [WorkShift, WorkShiftArrangement, ...WORK_SHIFT_REVISION_ENTITIES]\nexport const resolvers = [DomainWorkShiftQuery, WorkShiftQuery, WorkShiftMutation, WorkShiftLifecycleResolver]\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ShiftDefinition } from './work-shift-content';
|
|
2
|
+
/** Wall-clock rules use the signed zone. DST follows moment's earlier-offset/forward-gap rule. */
|
|
3
|
+
export declare function shiftOccurrence(shift: ShiftDefinition, workDate: string, timezone: string): {
|
|
4
|
+
name: string;
|
|
5
|
+
workDate: string;
|
|
6
|
+
from: Date;
|
|
7
|
+
to: Date;
|
|
8
|
+
};
|
|
9
|
+
export declare function shiftInfoAt(shifts: ShiftDefinition[], timezone: string, at: Date, validFrom?: Date, validTo?: Date | null): {
|
|
10
|
+
workDate: string;
|
|
11
|
+
workShift: string;
|
|
12
|
+
shiftRange: Date[];
|
|
13
|
+
dateRange: Date[];
|
|
14
|
+
} | {
|
|
15
|
+
workDate: string;
|
|
16
|
+
workShift: string;
|
|
17
|
+
dateRange: Date[];
|
|
18
|
+
shiftRange?: undefined;
|
|
19
|
+
};
|