@things-factory/work-shift 10.1.246 → 10.1.248

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/package.json +5 -5
  2. package/dist-client/bootstrap.d.ts +0 -1
  3. package/dist-client/bootstrap.js +0 -6
  4. package/dist-client/bootstrap.js.map +0 -1
  5. package/dist-client/index.d.ts +0 -0
  6. package/dist-client/index.js +0 -2
  7. package/dist-client/index.js.map +0 -1
  8. package/dist-client/pages/work-shift.d.ts +0 -105
  9. package/dist-client/pages/work-shift.js +0 -1144
  10. package/dist-client/pages/work-shift.js.map +0 -1
  11. package/dist-client/route.d.ts +0 -1
  12. package/dist-client/route.js +0 -8
  13. package/dist-client/route.js.map +0 -1
  14. package/dist-client/shift-coverage.d.ts +0 -102
  15. package/dist-client/shift-coverage.js +0 -196
  16. package/dist-client/shift-coverage.js.map +0 -1
  17. package/dist-client/shift-editing.d.ts +0 -80
  18. package/dist-client/shift-editing.js +0 -212
  19. package/dist-client/shift-editing.js.map +0 -1
  20. package/dist-client/shift-revisions.d.ts +0 -73
  21. package/dist-client/shift-revisions.js +0 -64
  22. package/dist-client/shift-revisions.js.map +0 -1
  23. package/dist-client/tsconfig.tsbuildinfo +0 -1
  24. package/dist-server/controllers/index.d.ts +0 -2
  25. package/dist-server/controllers/index.js +0 -6
  26. package/dist-server/controllers/index.js.map +0 -1
  27. package/dist-server/controllers/work-shift-range.d.ts +0 -28
  28. package/dist-server/controllers/work-shift-range.js +0 -65
  29. package/dist-server/controllers/work-shift-range.js.map +0 -1
  30. package/dist-server/controllers/work-shift-schedule.d.ts +0 -5
  31. package/dist-server/controllers/work-shift-schedule.js +0 -60
  32. package/dist-server/controllers/work-shift-schedule.js.map +0 -1
  33. package/dist-server/index.d.ts +0 -2
  34. package/dist-server/index.js +0 -19
  35. package/dist-server/index.js.map +0 -1
  36. package/dist-server/service/index.d.ts +0 -13
  37. package/dist-server/service/index.js +0 -33
  38. package/dist-server/service/index.js.map +0 -1
  39. package/dist-server/service/work-shift/days-of-week.d.ts +0 -30
  40. package/dist-server/service/work-shift/days-of-week.js +0 -74
  41. package/dist-server/service/work-shift/days-of-week.js.map +0 -1
  42. package/dist-server/service/work-shift/index.d.ts +0 -9
  43. package/dist-server/service/work-shift/index.js +0 -20
  44. package/dist-server/service/work-shift/index.js.map +0 -1
  45. package/dist-server/service/work-shift/shift-occurrence.d.ts +0 -19
  46. package/dist-server/service/work-shift/shift-occurrence.js +0 -34
  47. package/dist-server/service/work-shift/shift-occurrence.js.map +0 -1
  48. package/dist-server/service/work-shift/work-shift-arrangement.d.ts +0 -10
  49. package/dist-server/service/work-shift/work-shift-arrangement.js +0 -40
  50. package/dist-server/service/work-shift/work-shift-arrangement.js.map +0 -1
  51. package/dist-server/service/work-shift/work-shift-baseline.d.ts +0 -23
  52. package/dist-server/service/work-shift/work-shift-baseline.js +0 -55
  53. package/dist-server/service/work-shift/work-shift-baseline.js.map +0 -1
  54. package/dist-server/service/work-shift/work-shift-change-approval.d.ts +0 -14
  55. package/dist-server/service/work-shift/work-shift-change-approval.js +0 -64
  56. package/dist-server/service/work-shift/work-shift-change-approval.js.map +0 -1
  57. package/dist-server/service/work-shift/work-shift-content.d.ts +0 -18
  58. package/dist-server/service/work-shift/work-shift-content.js +0 -62
  59. package/dist-server/service/work-shift/work-shift-content.js.map +0 -1
  60. package/dist-server/service/work-shift/work-shift-lifecycle-resolver.d.ts +0 -68
  61. package/dist-server/service/work-shift/work-shift-lifecycle-resolver.js +0 -89
  62. package/dist-server/service/work-shift/work-shift-lifecycle-resolver.js.map +0 -1
  63. package/dist-server/service/work-shift/work-shift-lifecycle.d.ts +0 -229
  64. package/dist-server/service/work-shift/work-shift-lifecycle.js +0 -672
  65. package/dist-server/service/work-shift/work-shift-lifecycle.js.map +0 -1
  66. package/dist-server/service/work-shift/work-shift-mutation.d.ts +0 -16
  67. package/dist-server/service/work-shift/work-shift-mutation.js +0 -77
  68. package/dist-server/service/work-shift/work-shift-mutation.js.map +0 -1
  69. package/dist-server/service/work-shift/work-shift-query.d.ts +0 -14
  70. package/dist-server/service/work-shift/work-shift-query.js +0 -116
  71. package/dist-server/service/work-shift/work-shift-query.js.map +0 -1
  72. package/dist-server/service/work-shift/work-shift-revision-service.d.ts +0 -32
  73. package/dist-server/service/work-shift/work-shift-revision-service.js +0 -89
  74. package/dist-server/service/work-shift/work-shift-revision-service.js.map +0 -1
  75. package/dist-server/service/work-shift/work-shift-revision.d.ts +0 -85
  76. package/dist-server/service/work-shift/work-shift-revision.js +0 -337
  77. package/dist-server/service/work-shift/work-shift-revision.js.map +0 -1
  78. package/dist-server/service/work-shift/work-shift-selection.d.ts +0 -50
  79. package/dist-server/service/work-shift/work-shift-selection.js +0 -65
  80. package/dist-server/service/work-shift/work-shift-selection.js.map +0 -1
  81. package/dist-server/service/work-shift/work-shift-type.d.ts +0 -26
  82. package/dist-server/service/work-shift/work-shift-type.js +0 -77
  83. package/dist-server/service/work-shift/work-shift-type.js.map +0 -1
  84. package/dist-server/service/work-shift/work-shift.d.ts +0 -56
  85. package/dist-server/service/work-shift/work-shift.js +0 -109
  86. package/dist-server/service/work-shift/work-shift.js.map +0 -1
  87. package/dist-server/tsconfig.tsbuildinfo +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,iDAAiE;AAEjE,kFAAwF;AAExF,wDAA6B;AAC7B,oDAAyB;AAEzB;;;GAGG;AACH,OAAO,CAAC,EAAE,CAAC,wBAA+B,EAAE,GAAG,EAAE;IAC/C;;;OAGG;IACH,IAAA,kBAAU,EAAC,GAAG,EAAE,CAAC,IAAA,mDAA6B,EAAC,IAAA,qBAAa,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAC7E,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAC7E,CAAA;AACH,CAAC,CAAC,CAAA","sourcesContent":["import { getDataSource, inBootTurn } from '@things-factory/shell'\n\nimport { standWorkShiftBaselinesAtBoot } from './service/work-shift/work-shift-baseline'\n\nexport * from './controllers'\nexport * from './service'\n\n/*\n * 버전을 올린 설치본의 교대에 첫 편성 개정본을 세운다(2026-09-24). 이미 있으면 손대지 않으므로 기동마다\n * 불러도 된다. 무엇이 실패해도 던지지 않는다 — 서버를 반쯤 뜬 채로 두지 않는다(§`work-shift-baseline`).\n */\nprocess.on('bootstrap-module-start' as any, () => {\n /*\n * **기동의 한 줄에 선다**(`inBootTurn`, shell). 기준선은 도메인 · 축마다 트랜잭션을 여는데, 다른 모듈의 기동\n * 트랜잭션과 같은 SQLite 연결에서 겹치면 서로를 깨뜨린다(2026-09-24 — ops-master 와 work-shift 가 그랬다).\n */\n inBootTurn(() => standWorkShiftBaselinesAtBoot(getDataSource())).catch(error =>\n console.error(`[work-shift] 교대 기준선을 세우지 못했습니다 — ${error?.message ?? error}`)\n )\n})\n"]}
@@ -1,13 +0,0 @@
1
- export * from './work-shift/work-shift';
2
- export * from './work-shift/work-shift-revision';
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';
7
- export * from './work-shift/work-shift-baseline';
8
- export * from './work-shift/work-shift-change-approval';
9
- export * from './work-shift/days-of-week';
10
- export declare const entities: (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-arrangement").WorkShiftArrangement | typeof import("./work-shift/work-shift").WorkShift)[];
11
- export declare const schema: {
12
- resolverClasses: (typeof import("./work-shift/work-shift-change-approval").WorkShiftChangeApprovalResolver | 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)[];
13
- };
@@ -1,33 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.schema = exports.entities = void 0;
4
- const tslib_1 = require("tslib");
5
- /* EXPORT ENTITY TYPES */
6
- tslib_1.__exportStar(require("./work-shift/work-shift"), exports);
7
- tslib_1.__exportStar(require("./work-shift/work-shift-revision"), exports);
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);
12
- tslib_1.__exportStar(require("./work-shift/work-shift-baseline"), exports);
13
- tslib_1.__exportStar(require("./work-shift/work-shift-change-approval"), exports);
14
- /*
15
- * This file names each source file rather than re-exporting the folder barrel, so anything added
16
- * to that barrel stops at the package boundary unless it is also listed here. `daysOfWeek` is
17
- * stored as a CSV and every consumer has to parse it, so the parser has to be reachable — a
18
- * consumer that cannot import it writes its own, and the two disagree quietly.
19
- */
20
- tslib_1.__exportStar(require("./work-shift/days-of-week"), exports);
21
- /* IMPORT ENTITIES AND RESOLVERS */
22
- const work_shift_1 = require("./work-shift");
23
- exports.entities = [
24
- /* ENTITIES */
25
- ...work_shift_1.entities,
26
- ];
27
- exports.schema = {
28
- resolverClasses: [
29
- /* RESOLVER CLASSES */
30
- ...work_shift_1.resolvers,
31
- ]
32
- };
33
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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,2EAAgD;AAChD,kFAAuD;AACvD;;;;;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'\nexport * from './work-shift/work-shift-baseline'\nexport * from './work-shift/work-shift-change-approval'\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,30 +0,0 @@
1
- /** 0 Sunday … 6 Saturday, the same numbering `Date.getDay()` uses. */
2
- export type Weekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;
3
- /**
4
- * The weekdays this shift runs on, or `undefined` when it runs every day.
5
- *
6
- * Junk is dropped rather than throwing. This value comes from a column that a person can
7
- * edit and from clients written before the field existed; refusing to read a row because
8
- * one segment is wrong would take a whole site's calendar down for a typo. What is
9
- * dropped is a segment, and if every segment is junk the result is `undefined` — which is
10
- * the pre-existing behaviour, not a made-up restriction.
11
- */
12
- export declare function readDaysOfWeek(csv?: string | null): Weekday[] | undefined;
13
- /**
14
- * The stored form of a weekday list, or `undefined` for every day.
15
- *
16
- * Sorted and de-duplicated so that two ways of saying the same thing produce the same
17
- * string — otherwise a row looks changed when it is not, and the revision history fills
18
- * with edits nobody made.
19
- */
20
- export declare function writeDaysOfWeek(days?: readonly number[] | null): string | undefined;
21
- /**
22
- * Does this shift run on that date?
23
- *
24
- * ⚠ The weekday is read in the caller's timezone, because `Date.getDay()` is local. A
25
- * shift's days are stated against the site's calendar, so the date handed in must already
26
- * be in the site's time base — the same rule the shift's `HH:MM` already follows
27
- * (§`withSpaceTimeBase`). Handing in a UTC date for a site that is not on UTC will get
28
- * the wrong answer near midnight, silently.
29
- */
30
- export declare function runsOn(csv: string | null | undefined, when: Date): boolean;
@@ -1,74 +0,0 @@
1
- "use strict";
2
- /*
3
- * Reading and writing a shift's weekdays — pure, one place.
4
- *
5
- * ── Why this is not left to each consumer ─────────────────────────────────
6
- * The column is a CSV because array columns are not portable across the five drivers
7
- * things-factory supports. That means every reader has to parse it, and a parser written
8
- * twice will disagree eventually — on whitespace, on an out-of-range digit, on what an
9
- * empty string means. The disagreement would not raise anything: one consumer would think
10
- * the site rests on Sunday and another would not, and both would keep computing.
11
- *
12
- * So the string is written and read here, and the meaning is decided once.
13
- *
14
- * ── Empty means every day ─────────────────────────────────────────────────
15
- * Rows that predate the column have no value, and they must keep behaving as they did.
16
- * `undefined` is returned for that case rather than a full list of seven, so a caller can
17
- * still tell "no restriction was ever stated" from "someone chose all seven days". The
18
- * two are the same in effect and different in intent, and the second one is a person's
19
- * decision worth keeping.
20
- */
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.readDaysOfWeek = readDaysOfWeek;
23
- exports.writeDaysOfWeek = writeDaysOfWeek;
24
- exports.runsOn = runsOn;
25
- /**
26
- * The weekdays this shift runs on, or `undefined` when it runs every day.
27
- *
28
- * Junk is dropped rather than throwing. This value comes from a column that a person can
29
- * edit and from clients written before the field existed; refusing to read a row because
30
- * one segment is wrong would take a whole site's calendar down for a typo. What is
31
- * dropped is a segment, and if every segment is junk the result is `undefined` — which is
32
- * the pre-existing behaviour, not a made-up restriction.
33
- */
34
- function readDaysOfWeek(csv) {
35
- if (!csv || !csv.trim()) {
36
- return undefined;
37
- }
38
- const days = new Set();
39
- for (const part of csv.split(',')) {
40
- const n = Number(part.trim());
41
- if (Number.isInteger(n) && n >= 0 && n <= 6) {
42
- days.add(n);
43
- }
44
- }
45
- return days.size ? [...days].sort((a, b) => a - b) : undefined;
46
- }
47
- /**
48
- * The stored form of a weekday list, or `undefined` for every day.
49
- *
50
- * Sorted and de-duplicated so that two ways of saying the same thing produce the same
51
- * string — otherwise a row looks changed when it is not, and the revision history fills
52
- * with edits nobody made.
53
- */
54
- function writeDaysOfWeek(days) {
55
- if (!days?.length) {
56
- return undefined;
57
- }
58
- const kept = readDaysOfWeek(days.join(','));
59
- return kept?.join(',');
60
- }
61
- /**
62
- * Does this shift run on that date?
63
- *
64
- * ⚠ The weekday is read in the caller's timezone, because `Date.getDay()` is local. A
65
- * shift's days are stated against the site's calendar, so the date handed in must already
66
- * be in the site's time base — the same rule the shift's `HH:MM` already follows
67
- * (§`withSpaceTimeBase`). Handing in a UTC date for a site that is not on UTC will get
68
- * the wrong answer near midnight, silently.
69
- */
70
- function runsOn(csv, when) {
71
- const days = readDaysOfWeek(csv);
72
- return days === undefined || days.includes(when.getDay());
73
- }
74
- //# sourceMappingURL=days-of-week.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"days-of-week.js","sourceRoot":"","sources":["../../../server/service/work-shift/days-of-week.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;AAcH,wCAgBC;AASD,0CAQC;AAWD,wBAIC;AAzDD;;;;;;;;GAQG;AACH,SAAgB,cAAc,CAAC,GAAmB;IAChD,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QACxB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAA;IAE/B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QAE7B,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,CAAY,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAChE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,IAA+B;IAC7D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAE3C,OAAO,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,MAAM,CAAC,GAA8B,EAAE,IAAU;IAC/D,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;IAEhC,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAa,CAAC,CAAA;AACtE,CAAC","sourcesContent":["/*\n * Reading and writing a shift's weekdays — pure, one place.\n *\n * ── Why this is not left to each consumer ─────────────────────────────────\n * The column is a CSV because array columns are not portable across the five drivers\n * things-factory supports. That means every reader has to parse it, and a parser written\n * twice will disagree eventually — on whitespace, on an out-of-range digit, on what an\n * empty string means. The disagreement would not raise anything: one consumer would think\n * the site rests on Sunday and another would not, and both would keep computing.\n *\n * So the string is written and read here, and the meaning is decided once.\n *\n * ── Empty means every day ─────────────────────────────────────────────────\n * Rows that predate the column have no value, and they must keep behaving as they did.\n * `undefined` is returned for that case rather than a full list of seven, so a caller can\n * still tell \"no restriction was ever stated\" from \"someone chose all seven days\". The\n * two are the same in effect and different in intent, and the second one is a person's\n * decision worth keeping.\n */\n\n/** 0 Sunday … 6 Saturday, the same numbering `Date.getDay()` uses. */\nexport type Weekday = 0 | 1 | 2 | 3 | 4 | 5 | 6\n\n/**\n * The weekdays this shift runs on, or `undefined` when it runs every day.\n *\n * Junk is dropped rather than throwing. This value comes from a column that a person can\n * edit and from clients written before the field existed; refusing to read a row because\n * one segment is wrong would take a whole site's calendar down for a typo. What is\n * dropped is a segment, and if every segment is junk the result is `undefined` — which is\n * the pre-existing behaviour, not a made-up restriction.\n */\nexport function readDaysOfWeek(csv?: string | null): Weekday[] | undefined {\n if (!csv || !csv.trim()) {\n return undefined\n }\n\n const days = new Set<Weekday>()\n\n for (const part of csv.split(',')) {\n const n = Number(part.trim())\n\n if (Number.isInteger(n) && n >= 0 && n <= 6) {\n days.add(n as Weekday)\n }\n }\n\n return days.size ? [...days].sort((a, b) => a - b) : undefined\n}\n\n/**\n * The stored form of a weekday list, or `undefined` for every day.\n *\n * Sorted and de-duplicated so that two ways of saying the same thing produce the same\n * string — otherwise a row looks changed when it is not, and the revision history fills\n * with edits nobody made.\n */\nexport function writeDaysOfWeek(days?: readonly number[] | null): string | undefined {\n if (!days?.length) {\n return undefined\n }\n\n const kept = readDaysOfWeek(days.join(','))\n\n return kept?.join(',')\n}\n\n/**\n * Does this shift run on that date?\n *\n * ⚠ The weekday is read in the caller's timezone, because `Date.getDay()` is local. A\n * shift's days are stated against the site's calendar, so the date handed in must already\n * be in the site's time base — the same rule the shift's `HH:MM` already follows\n * (§`withSpaceTimeBase`). Handing in a UTC date for a site that is not on UTC will get\n * the wrong answer near midnight, silently.\n */\nexport function runsOn(csv: string | null | undefined, when: Date): boolean {\n const days = readDaysOfWeek(csv)\n\n return days === undefined || days.includes(when.getDay() as Weekday)\n}\n"]}
@@ -1,9 +0,0 @@
1
- import { DomainWorkShiftQuery, WorkShiftQuery } from './work-shift-query';
2
- import { WorkShift } from './work-shift';
3
- import { WorkShiftMutation } from './work-shift-mutation';
4
- import { WorkShiftLifecycleResolver } from './work-shift-lifecycle-resolver';
5
- import { WorkShiftArrangement } from './work-shift-arrangement';
6
- import { WorkShiftChangeApprovalResolver } from './work-shift-change-approval';
7
- export * from './days-of-week';
8
- export declare const entities: (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 WorkShiftArrangement | typeof WorkShift)[];
9
- export declare const resolvers: (typeof WorkShiftChangeApprovalResolver | typeof DomainWorkShiftQuery | typeof WorkShiftQuery | typeof WorkShiftMutation | typeof WorkShiftLifecycleResolver)[];
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolvers = exports.entities = void 0;
4
- const tslib_1 = require("tslib");
5
- const work_shift_query_1 = require("./work-shift-query");
6
- const work_shift_1 = require("./work-shift");
7
- const work_shift_mutation_1 = require("./work-shift-mutation");
8
- const work_shift_lifecycle_resolver_1 = require("./work-shift-lifecycle-resolver");
9
- const work_shift_revision_1 = require("./work-shift-revision");
10
- const work_shift_arrangement_1 = require("./work-shift-arrangement");
11
- const work_shift_change_approval_1 = require("./work-shift-change-approval");
12
- /*
13
- * The weekday rule is exported so consumers read the column through one parser. It is a CSV
14
- * because array columns are not portable across the five drivers, and a parser written twice
15
- * disagrees eventually — quietly, since both halves keep computing (§`days-of-week.ts`).
16
- */
17
- tslib_1.__exportStar(require("./days-of-week"), exports);
18
- exports.entities = [work_shift_1.WorkShift, work_shift_arrangement_1.WorkShiftArrangement, ...work_shift_revision_1.WORK_SHIFT_REVISION_ENTITIES];
19
- exports.resolvers = [work_shift_query_1.DomainWorkShiftQuery, work_shift_query_1.WorkShiftQuery, work_shift_mutation_1.WorkShiftMutation, work_shift_lifecycle_resolver_1.WorkShiftLifecycleResolver, work_shift_change_approval_1.WorkShiftChangeApprovalResolver];
20
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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;AAC/D,6EAA8E;AAE9E;;;;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,EAAE,4DAA+B,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'\nimport { WorkShiftChangeApprovalResolver } from './work-shift-change-approval'\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, WorkShiftChangeApprovalResolver]\n"]}
@@ -1,19 +0,0 @@
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
- };
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shiftOccurrence = shiftOccurrence;
4
- exports.shiftInfoAt = shiftInfoAt;
5
- const tslib_1 = require("tslib");
6
- const moment_timezone_1 = tslib_1.__importDefault(require("moment-timezone"));
7
- /** Wall-clock rules use the signed zone. DST follows moment's earlier-offset/forward-gap rule. */
8
- function shiftOccurrence(shift, workDate, timezone) {
9
- const day = moment_timezone_1.default.tz(workDate, 'YYYY-MM-DD', true, timezone);
10
- if (!day.isValid())
11
- throw new Error('Invalid work date');
12
- if (shift.daysOfWeek && !shift.daysOfWeek.split(',').includes(String(day.day())))
13
- return undefined;
14
- const clock = (offset, time) => moment_timezone_1.default.tz(day.clone().add(offset, 'day').format('YYYY-MM-DD') + ' ' + time, 'YYYY-MM-DD HH:mm', timezone).toDate();
15
- const from = clock(shift.fromDate, shift.fromTime), to = clock(shift.toDate, shift.toTime);
16
- return to > from ? { name: shift.name, workDate, from, to } : undefined;
17
- }
18
- function shiftInfoAt(shifts, timezone, at, validFrom, validTo) {
19
- const today = (0, moment_timezone_1.default)(at).tz(timezone).startOf('day');
20
- for (const offset of [-1, 0, 1]) {
21
- const workDate = today.clone().add(offset, 'day').format('YYYY-MM-DD');
22
- const windows = shifts.map(s => shiftOccurrence(s, workDate, timezone)).filter(Boolean);
23
- const hit = windows.find(w => w.from <= at && w.to > at);
24
- if (hit) {
25
- const from = new Date(Math.max(hit.from.getTime(), validFrom?.getTime() ?? -Infinity));
26
- const to = new Date(Math.min(hit.to.getTime(), validTo?.getTime() ?? Infinity));
27
- return { workDate, workShift: hit.name, shiftRange: [from, to],
28
- dateRange: [new Date(Math.max(Math.min(...windows.map(w => w.from.getTime())), validFrom?.getTime() ?? -Infinity)),
29
- new Date(Math.min(Math.max(...windows.map(w => w.to.getTime())), validTo?.getTime() ?? Infinity))] };
30
- }
31
- }
32
- return { workDate: today.format('YYYY-MM-DD'), workShift: '', dateRange: [today.toDate(), today.clone().add(1, 'day').toDate()] };
33
- }
34
- //# sourceMappingURL=shift-occurrence.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shift-occurrence.js","sourceRoot":"","sources":["../../../server/service/work-shift/shift-occurrence.ts"],"names":[],"mappings":";;AAIA,0CAOC;AAED,kCAeC;;AA5BD,8EAAoC;AAGpC,kGAAkG;AAClG,SAAgB,eAAe,CAAC,KAAsB,EAAE,QAAgB,EAAE,QAAgB;IACxF,MAAM,GAAG,GAAG,yBAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC7D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;IACxD,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAClG,MAAM,KAAK,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,EAAE,CAAC,yBAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,GAAG,IAAI,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAA;IAClK,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1F,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACzE,CAAC;AAED,SAAgB,WAAW,CAAC,MAAyB,EAAE,QAAgB,EAAE,EAAQ,EAAE,SAAgB,EAAE,OAAqB;IACxH,MAAM,KAAK,GAAG,IAAA,yBAAM,EAAC,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACpD,KAAK,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;QACtE,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACvF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QACxD,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;YACtF,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,QAAQ,CAAC,CAAC,CAAA;YAC/E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC5D,SAAS,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAChH,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1G,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,EAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAA;AAClI,CAAC","sourcesContent":["import moment from 'moment-timezone'\nimport type { ShiftDefinition } from './work-shift-content'\n\n/** Wall-clock rules use the signed zone. DST follows moment's earlier-offset/forward-gap rule. */\nexport function shiftOccurrence(shift: ShiftDefinition, workDate: string, timezone: string) {\n const day = moment.tz(workDate, 'YYYY-MM-DD', true, timezone)\n if (!day.isValid()) throw new Error('Invalid work date')\n if (shift.daysOfWeek && !shift.daysOfWeek.split(',').includes(String(day.day()))) return undefined\n const clock = (offset: number, time: string) => moment.tz(day.clone().add(offset, 'day').format('YYYY-MM-DD') + ' ' + time, 'YYYY-MM-DD HH:mm', timezone).toDate()\n const from = clock(shift.fromDate, shift.fromTime), to = clock(shift.toDate, shift.toTime)\n return to > from ? { name: shift.name, workDate, from, to } : undefined\n}\n\nexport function shiftInfoAt(shifts: ShiftDefinition[], timezone: string, at: Date, validFrom?: Date, validTo?: Date | null) {\n const today = moment(at).tz(timezone).startOf('day')\n for (const offset of [-1, 0, 1]) {\n const workDate = today.clone().add(offset, 'day').format('YYYY-MM-DD')\n const windows = shifts.map(s => shiftOccurrence(s, workDate, timezone)).filter(Boolean)\n const hit = windows.find(w => w.from <= at && w.to > at)\n if (hit) {\n const from = new Date(Math.max(hit.from.getTime(), validFrom?.getTime() ?? -Infinity))\n const to = new Date(Math.min(hit.to.getTime(), validTo?.getTime() ?? Infinity))\n return { workDate, workShift: hit.name, shiftRange: [from, to],\n dateRange: [new Date(Math.max(Math.min(...windows.map(w => w.from.getTime())), validFrom?.getTime() ?? -Infinity)),\n new Date(Math.min(Math.max(...windows.map(w => w.to.getTime())), validTo?.getTime() ?? Infinity))] }\n }\n }\n return { workDate: today.format('YYYY-MM-DD'), workShift: '', dateRange: [today.toDate(), today.clone().add(1,'day').toDate()] }\n}\n"]}
@@ -1,10 +0,0 @@
1
- import { Domain } from '@things-factory/shell';
2
- /** One identity per domain; revision content is the entire shift arrangement. */
3
- export declare class WorkShiftArrangement {
4
- id: string;
5
- domain: Domain;
6
- domainId: string;
7
- name: string;
8
- planGeneration: number;
9
- revisionLock: number;
10
- }
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WorkShiftArrangement = void 0;
4
- const tslib_1 = require("tslib");
5
- const typeorm_1 = require("typeorm");
6
- const shell_1 = require("@things-factory/shell");
7
- /** One identity per domain; revision content is the entire shift arrangement. */
8
- let WorkShiftArrangement = class WorkShiftArrangement {
9
- };
10
- exports.WorkShiftArrangement = WorkShiftArrangement;
11
- tslib_1.__decorate([
12
- (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
13
- tslib_1.__metadata("design:type", String)
14
- ], WorkShiftArrangement.prototype, "id", void 0);
15
- tslib_1.__decorate([
16
- (0, typeorm_1.ManyToOne)(() => shell_1.Domain, { nullable: false }),
17
- tslib_1.__metadata("design:type", shell_1.Domain)
18
- ], WorkShiftArrangement.prototype, "domain", void 0);
19
- tslib_1.__decorate([
20
- (0, typeorm_1.RelationId)((row) => row.domain),
21
- tslib_1.__metadata("design:type", String)
22
- ], WorkShiftArrangement.prototype, "domainId", void 0);
23
- tslib_1.__decorate([
24
- (0, typeorm_1.Column)({ default: 'Work shifts' }),
25
- tslib_1.__metadata("design:type", String)
26
- ], WorkShiftArrangement.prototype, "name", void 0);
27
- tslib_1.__decorate([
28
- (0, typeorm_1.Column)('int', { default: 0 }),
29
- tslib_1.__metadata("design:type", Number)
30
- ], WorkShiftArrangement.prototype, "planGeneration", void 0);
31
- tslib_1.__decorate([
32
- (0, typeorm_1.Column)('int', { default: 0 }),
33
- tslib_1.__metadata("design:type", Number)
34
- ], WorkShiftArrangement.prototype, "revisionLock", void 0);
35
- exports.WorkShiftArrangement = WorkShiftArrangement = tslib_1.__decorate([
36
- (0, typeorm_1.Entity)(),
37
- (0, typeorm_1.Index)('ix_shift_arrangement_domain', ['domain'], { unique: true }),
38
- (0, typeorm_1.Index)('ix_shift_arrangement_identity', ['domain', 'id'], { unique: true })
39
- ], WorkShiftArrangement);
40
- //# sourceMappingURL=work-shift-arrangement.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"work-shift-arrangement.js","sourceRoot":"","sources":["../../../server/service/work-shift/work-shift-arrangement.ts"],"names":[],"mappings":";;;;AAAA,qCAA8F;AAC9F,iDAA8C;AAE9C,iFAAiF;AAI1E,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAOhC,CAAA;AAPY,oDAAoB;AACC;IAA/B,IAAA,gCAAsB,EAAC,MAAM,CAAC;;gDAAW;AACI;IAA7C,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;sCAAS,cAAM;oDAAA;AACL;IAAtD,IAAA,oBAAU,EAAC,CAAC,GAAyB,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;;sDAAiB;AACnC;IAAnC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;;kDAAa;AACjB;IAA9B,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;4DAAuB;AACtB;IAA9B,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;0DAAqB;+BANxC,oBAAoB;IAHhC,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,6BAA6B,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAClE,IAAA,eAAK,EAAC,+BAA+B,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;GAC9D,oBAAoB,CAOhC","sourcesContent":["import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\nimport { Domain } from '@things-factory/shell'\n\n/** One identity per domain; revision content is the entire shift arrangement. */\n@Entity()\n@Index('ix_shift_arrangement_domain', ['domain'], { unique: true })\n@Index('ix_shift_arrangement_identity', ['domain', 'id'], { unique: true })\nexport class WorkShiftArrangement {\n @PrimaryGeneratedColumn('uuid') id: string\n @ManyToOne(() => Domain, { nullable: false }) domain: Domain\n @RelationId((row: WorkShiftArrangement) => row.domain) domainId: string\n @Column({ default: 'Work shifts' }) name: string\n @Column('int', { default: 0 }) planGeneration: number\n @Column('int', { default: 0 }) revisionLock: number\n}\n"]}
@@ -1,23 +0,0 @@
1
- import { DataSource } from 'typeorm';
2
- import { Domain } from '@things-factory/shell';
3
- /**
4
- * 버전을 올린 설치본의 교대에 첫 편성 개정본을 세운다 — 기준선(2026-09-24). 규칙은 ops-master 의
5
- * `revision-baseline` 과 같다. 편성은 이 패키지의 것이라 여기서 세운다 — ops-master 는 이 패키지를 모른다.
6
- *
7
- * 사업장마다 트랜잭션 하나. 하나가 실패해도 나머지는 선다. 실패한 사업장을 크게 말하고, 던지지 않는다.
8
- */
9
- export interface WorkShiftBaselineReport {
10
- domain: string;
11
- stood: number;
12
- unreadable: {
13
- name: string;
14
- problem: string;
15
- }[];
16
- failed?: string;
17
- }
18
- export declare function workShiftBaselineEdition(): string;
19
- export declare function standWorkShiftBaselines(dataSource: DataSource, options?: {
20
- edition?: string;
21
- domains?: Domain[];
22
- }): Promise<WorkShiftBaselineReport[]>;
23
- export declare function standWorkShiftBaselinesAtBoot(dataSource: DataSource): Promise<WorkShiftBaselineReport[]>;
@@ -1,55 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.workShiftBaselineEdition = workShiftBaselineEdition;
4
- exports.standWorkShiftBaselines = standWorkShiftBaselines;
5
- exports.standWorkShiftBaselinesAtBoot = standWorkShiftBaselinesAtBoot;
6
- const shell_1 = require("@things-factory/shell");
7
- const ops_master_1 = require("@things-factory/ops-master");
8
- const work_shift_lifecycle_1 = require("./work-shift-lifecycle");
9
- function workShiftBaselineEdition() {
10
- try {
11
- return `@things-factory/work-shift ${require('../../../package.json').version}`;
12
- }
13
- catch {
14
- return '@things-factory/work-shift';
15
- }
16
- }
17
- async function standWorkShiftBaselines(dataSource, options = {}) {
18
- const edition = options.edition ?? workShiftBaselineEdition();
19
- const domains = options.domains ?? (await dataSource.getRepository(shell_1.Domain).find());
20
- const reports = [];
21
- for (const domain of domains) {
22
- const at = new Date();
23
- try {
24
- const outcome = await dataSource.transaction(manager => (0, work_shift_lifecycle_1.standWorkShiftBaseline)(manager, domain.id, at, edition));
25
- reports.push({ domain: domain.name, ...outcome });
26
- }
27
- catch (error) {
28
- reports.push({ domain: domain.name, stood: 0, unreadable: [], failed: (0, ops_master_1.baselineFailureText)(error) });
29
- }
30
- }
31
- return reports;
32
- }
33
- async function standWorkShiftBaselinesAtBoot(dataSource) {
34
- let reports;
35
- try {
36
- reports = await standWorkShiftBaselines(dataSource);
37
- }
38
- catch (error) {
39
- console.error(`[work-shift] 교대 기준선을 세우지 못했습니다 — 사업장을 읽지 못함: ${error?.message ?? error}`);
40
- return [];
41
- }
42
- for (const report of reports) {
43
- if (report.failed) {
44
- console.error(`[work-shift] ⚠ 교대 기준선을 세우지 못했습니다 — ${report.domain}: ${report.failed}. 이 사업장의 실적은 교대 없이 적힙니다.`);
45
- continue;
46
- }
47
- if (report.stood)
48
- console.info(`[work-shift] 교대 기준선 ${report.domain}: 지금의 교대를 첫 편성 개정본으로 세웠습니다`);
49
- for (const one of report.unreadable) {
50
- console.warn(`[work-shift] ⚠ 교대 기준선을 못 세웠습니다 — ${report.domain} · ${one.name}: ${one.problem}`);
51
- }
52
- }
53
- return reports;
54
- }
55
- //# sourceMappingURL=work-shift-baseline.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"work-shift-baseline.js","sourceRoot":"","sources":["../../../server/service/work-shift/work-shift-baseline.ts"],"names":[],"mappings":";;AAmBA,4DAMC;AAED,0DAiBC;AAED,sEAmBC;AAhED,iDAA8C;AAC9C,2DAAgE;AAEhE,iEAA+D;AAe/D,SAAgB,wBAAwB;IACtC,IAAI,CAAC;QACH,OAAO,8BAA8B,OAAO,CAAC,uBAAuB,CAAC,CAAC,OAAO,EAAE,CAAA;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,4BAA4B,CAAA;IACrC,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,uBAAuB,CAC3C,UAAsB,EACtB,UAAoD,EAAE;IAEtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,EAAE,CAAA;IAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,cAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAClF,MAAM,OAAO,GAA8B,EAAE,CAAA;IAC7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAA;QACrB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,IAAA,6CAAsB,EAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;YAChH,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;QACnD,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,IAAA,gCAAmB,EAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACrG,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAEM,KAAK,UAAU,6BAA6B,CAAC,UAAsB;IACxE,IAAI,OAAkC,CAAA;IACtC,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAA;IACrD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,gDAAgD,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAAA;QACxF,OAAO,EAAE,CAAA;IACX,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,sCAAsC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,0BAA0B,CAAC,CAAA;YAC9G,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,CAAC,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,MAAM,4BAA4B,CAAC,CAAA;QAChG,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;QACjG,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import { DataSource } from 'typeorm'\nimport { Domain } from '@things-factory/shell'\nimport { baselineFailureText } from '@things-factory/ops-master'\n\nimport { standWorkShiftBaseline } from './work-shift-lifecycle'\n\n/**\n * 버전을 올린 설치본의 교대에 첫 편성 개정본을 세운다 — 기준선(2026-09-24). 규칙은 ops-master 의\n * `revision-baseline` 과 같다. 편성은 이 패키지의 것이라 여기서 세운다 — ops-master 는 이 패키지를 모른다.\n *\n * 사업장마다 트랜잭션 하나. 하나가 실패해도 나머지는 선다. 실패한 사업장을 크게 말하고, 던지지 않는다.\n */\nexport interface WorkShiftBaselineReport {\n domain: string\n stood: number\n unreadable: { name: string; problem: string }[]\n failed?: string\n}\n\nexport function workShiftBaselineEdition(): string {\n try {\n return `@things-factory/work-shift ${require('../../../package.json').version}`\n } catch {\n return '@things-factory/work-shift'\n }\n}\n\nexport async function standWorkShiftBaselines(\n dataSource: DataSource,\n options: { edition?: string; domains?: Domain[] } = {}\n): Promise<WorkShiftBaselineReport[]> {\n const edition = options.edition ?? workShiftBaselineEdition()\n const domains = options.domains ?? (await dataSource.getRepository(Domain).find())\n const reports: WorkShiftBaselineReport[] = []\n for (const domain of domains) {\n const at = new Date()\n try {\n const outcome = await dataSource.transaction(manager => standWorkShiftBaseline(manager, domain.id, at, edition))\n reports.push({ domain: domain.name, ...outcome })\n } catch (error: any) {\n reports.push({ domain: domain.name, stood: 0, unreadable: [], failed: baselineFailureText(error) })\n }\n }\n return reports\n}\n\nexport async function standWorkShiftBaselinesAtBoot(dataSource: DataSource) {\n let reports: WorkShiftBaselineReport[]\n try {\n reports = await standWorkShiftBaselines(dataSource)\n } catch (error: any) {\n console.error(`[work-shift] 교대 기준선을 세우지 못했습니다 — 사업장을 읽지 못함: ${error?.message ?? error}`)\n return []\n }\n for (const report of reports) {\n if (report.failed) {\n console.error(`[work-shift] ⚠ 교대 기준선을 세우지 못했습니다 — ${report.domain}: ${report.failed}. 이 사업장의 실적은 교대 없이 적힙니다.`)\n continue\n }\n if (report.stood) console.info(`[work-shift] 교대 기준선 ${report.domain}: 지금의 교대를 첫 편성 개정본으로 세웠습니다`)\n for (const one of report.unreadable) {\n console.warn(`[work-shift] ⚠ 교대 기준선을 못 세웠습니다 — ${report.domain} · ${one.name}: ${one.problem}`)\n }\n }\n return reports\n}\n"]}
@@ -1,14 +0,0 @@
1
- import { type MasterChangeAxis } from '@things-factory/ops-master';
2
- /**
3
- * The shift arrangement goes through the master-change approval ops-master owns (ADR-0086 decision 1,
4
- * amended 2026-10-10). Its revision steps live here, so this package registers its axis; ops-master
5
- * cannot import work-shift, which already depends on it.
6
- */
7
- export declare const WORK_SHIFT_CHANGE: MasterChangeAxis;
8
- export declare class WorkShiftChangeApprovalResolver {
9
- submitWorkShiftDraft(revisionId: string, editGeneration: number, context: ResolverContext): Promise<{
10
- revisionId: string;
11
- activityInstanceId: string;
12
- contentHash?: string;
13
- }>;
14
- }
@@ -1,64 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WorkShiftChangeApprovalResolver = exports.WORK_SHIFT_CHANGE = void 0;
4
- const tslib_1 = require("tslib");
5
- const type_graphql_1 = require("type-graphql");
6
- const ops_master_1 = require("@things-factory/ops-master");
7
- const shell_1 = require("@things-factory/shell");
8
- const work_shift_lifecycle_1 = require("./work-shift-lifecycle");
9
- /**
10
- * The shift arrangement goes through the master-change approval ops-master owns (ADR-0086 decision 1,
11
- * amended 2026-10-10). Its revision steps live here, so this package registers its axis; ops-master
12
- * cannot import work-shift, which already depends on it.
13
- */
14
- exports.WORK_SHIFT_CHANGE = {
15
- axis: 'workShift',
16
- activity: 'WorkShiftChangeApproval',
17
- label: 'shift pattern change approval',
18
- description: 'Approve the complete shift arrangement, time zone and effective date',
19
- category: 'schedule',
20
- guide: [
21
- 'Compare the previous and proposed definition and check when the new definition will apply.',
22
- 'Approval publishes this exact revision. It does not change executions already recorded.',
23
- 'An empty approval line refuses submission. The author cannot approve their own change.'
24
- ],
25
- readiness: {
26
- stage: 'partial',
27
- tests: ['things-factory/packages/work-shift/test/work-shift-change-approval.db.test.cjs'],
28
- gaps: ['Holiday and location calendar revision closure requires separate work.'],
29
- notes: 'Declared regulated axes require this approval. Non-regulated publication records its policy and publisher. Recorded executions keep their exact revision.'
30
- },
31
- before: 'previous definition',
32
- after: 'proposed definition',
33
- issuedAs: '교대 편성 변경',
34
- caveat: 'The signed revision stays. Correct it with another approved revision; recorded executions keep their basis.',
35
- Refusal: work_shift_lifecycle_1.WorkShiftRefusal,
36
- freeze: work_shift_lifecycle_1.freezeWorkShiftDraft,
37
- approvalInput: work_shift_lifecycle_1.workShiftApprovalInput,
38
- bind: work_shift_lifecycle_1.bindWorkShiftApproval,
39
- assertApprovalInput: work_shift_lifecycle_1.assertWorkShiftApprovalInput,
40
- publish: work_shift_lifecycle_1.publishWorkShiftRevision
41
- };
42
- (0, ops_master_1.installMasterChangeAxis)(exports.WORK_SHIFT_CHANGE, 'work-shift');
43
- let WorkShiftChangeApprovalResolver = class WorkShiftChangeApprovalResolver {
44
- async submitWorkShiftDraft(revisionId, editGeneration, context) {
45
- return (0, ops_master_1.submitMasterChangeDraft)('workShift', revisionId, editGeneration, context);
46
- }
47
- };
48
- exports.WorkShiftChangeApprovalResolver = WorkShiftChangeApprovalResolver;
49
- tslib_1.__decorate([
50
- (0, type_graphql_1.Directive)('@privilege(category: "work-shift", privilege: "mutation", domainOwnerGranted: true)'),
51
- (0, type_graphql_1.Directive)('@transaction'),
52
- (0, type_graphql_1.Mutation)(() => shell_1.ScalarObject, { description: 'Submit a shift arrangement draft for approval' }),
53
- tslib_1.__param(0, (0, type_graphql_1.Arg)('revisionId')),
54
- tslib_1.__param(1, (0, type_graphql_1.Arg)('editGeneration', () => type_graphql_1.Int)),
55
- tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
56
- tslib_1.__metadata("design:type", Function),
57
- tslib_1.__metadata("design:paramtypes", [String, Number, Object]),
58
- tslib_1.__metadata("design:returntype", Promise)
59
- ], WorkShiftChangeApprovalResolver.prototype, "submitWorkShiftDraft", null);
60
- exports.WorkShiftChangeApprovalResolver = WorkShiftChangeApprovalResolver = tslib_1.__decorate([
61
- (0, type_graphql_1.Resolver)(),
62
- (0, type_graphql_1.UseMiddleware)(shell_1.SpeakRefusals)
63
- ], WorkShiftChangeApprovalResolver);
64
- //# sourceMappingURL=work-shift-change-approval.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"work-shift-change-approval.js","sourceRoot":"","sources":["../../../server/service/work-shift/work-shift-change-approval.ts"],"names":[],"mappings":";;;;AAAA,+CAA0F;AAE1F,2DAAoH;AACpH,iDAAmE;AAEnE,iEAO+B;AAE/B;;;;GAIG;AACU,QAAA,iBAAiB,GAAqB;IACjD,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,yBAAyB;IACnC,KAAK,EAAE,+BAA+B;IACtC,WAAW,EAAE,sEAAsE;IACnF,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE;QACL,4FAA4F;QAC5F,yFAAyF;QACzF,wFAAwF;KACzF;IACD,SAAS,EAAE;QACT,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,CAAC,gFAAgF,CAAC;QACzF,IAAI,EAAE,CAAC,wEAAwE,CAAC;QAChF,KAAK,EAAE,2JAA2J;KACnK;IACD,MAAM,EAAE,qBAAqB;IAC7B,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,6GAA6G;IACrH,OAAO,EAAE,uCAAuB;IAChC,MAAM,EAAE,2CAA2B;IACnC,aAAa,EAAE,6CAA6B;IAC5C,IAAI,EAAE,4CAA4B;IAClC,mBAAmB,EAAE,mDAAmC;IACxD,OAAO,EAAE,+CAA+B;CACzC,CAAA;AAED,IAAA,oCAAuB,EAAC,yBAAiB,EAAE,YAAY,CAAC,CAAA;AAIjD,IAAM,+BAA+B,GAArC,MAAM,+BAA+B;IAIpC,AAAN,KAAK,CAAC,oBAAoB,CACL,UAAkB,EACH,cAAsB,EACjD,OAAwB;QAE/B,OAAO,IAAA,oCAAuB,EAAC,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAA;IAClF,CAAC;CACF,CAAA;AAXY,0EAA+B;AAIpC;IAHL,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,GAAG,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;IAE5F,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,EAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,kBAAG,CAAC,CAAA;IAChC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2EAGP;0CAVU,+BAA+B;IAF3C,IAAA,uBAAQ,GAAE;IACV,IAAA,4BAAa,EAAC,qBAAa,CAAC;GAChB,+BAA+B,CAW3C","sourcesContent":["import { Arg, Ctx, Directive, Int, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { installMasterChangeAxis, submitMasterChangeDraft, type MasterChangeAxis } from '@things-factory/ops-master'\nimport { ScalarObject, SpeakRefusals } from '@things-factory/shell'\n\nimport {\n assertWorkShiftApprovalInput,\n bindWorkShiftApproval,\n freezeWorkShiftDraft,\n publishWorkShiftRevision,\n workShiftApprovalInput,\n WorkShiftRefusal\n} from './work-shift-lifecycle'\n\n/**\n * The shift arrangement goes through the master-change approval ops-master owns (ADR-0086 decision 1,\n * amended 2026-10-10). Its revision steps live here, so this package registers its axis; ops-master\n * cannot import work-shift, which already depends on it.\n */\nexport const WORK_SHIFT_CHANGE: MasterChangeAxis = {\n axis: 'workShift',\n activity: 'WorkShiftChangeApproval',\n label: 'shift pattern change approval',\n description: 'Approve the complete shift arrangement, time zone and effective date',\n category: 'schedule',\n guide: [\n 'Compare the previous and proposed definition and check when the new definition will apply.',\n 'Approval publishes this exact revision. It does not change executions already recorded.',\n 'An empty approval line refuses submission. The author cannot approve their own change.'\n ],\n readiness: {\n stage: 'partial',\n tests: ['things-factory/packages/work-shift/test/work-shift-change-approval.db.test.cjs'],\n gaps: ['Holiday and location calendar revision closure requires separate work.'],\n notes: 'Declared regulated axes require this approval. Non-regulated publication records its policy and publisher. Recorded executions keep their exact revision.'\n },\n before: 'previous definition',\n after: 'proposed definition',\n issuedAs: '교대 편성 변경',\n caveat: 'The signed revision stays. Correct it with another approved revision; recorded executions keep their basis.',\n Refusal: WorkShiftRefusal as any,\n freeze: freezeWorkShiftDraft as any,\n approvalInput: workShiftApprovalInput as any,\n bind: bindWorkShiftApproval as any,\n assertApprovalInput: assertWorkShiftApprovalInput as any,\n publish: publishWorkShiftRevision as any\n}\n\ninstallMasterChangeAxis(WORK_SHIFT_CHANGE, 'work-shift')\n\n@Resolver()\n@UseMiddleware(SpeakRefusals)\nexport class WorkShiftChangeApprovalResolver {\n @Directive('@privilege(category: \"work-shift\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(() => ScalarObject, { description: 'Submit a shift arrangement draft for approval' })\n async submitWorkShiftDraft(\n @Arg('revisionId') revisionId: string,\n @Arg('editGeneration', () => Int) editGeneration: number,\n @Ctx() context: ResolverContext\n ) {\n return submitMasterChangeDraft('workShift', revisionId, editGeneration, context)\n }\n}\n"]}
@@ -1,18 +0,0 @@
1
- import type { WorkShift } from './work-shift';
2
- export interface ShiftDefinition {
3
- name: string;
4
- description?: string;
5
- fromDate: number;
6
- fromTime: string;
7
- toDate: number;
8
- toTime: string;
9
- daysOfWeek: string;
10
- }
11
- /** Weekdays refer to the work date, including shifts starting the previous/next day. */
12
- export declare function shiftDraftContent(input: any, stored?: boolean): {
13
- description: any;
14
- timezone: string;
15
- shifts: ShiftDefinition[];
16
- };
17
- /** Every field affecting execution belongs to the signed arrangement. */
18
- export declare function shiftSetOf(shifts: Partial<WorkShift>[]): Record<string, unknown>[];
@@ -1,62 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shiftDraftContent = shiftDraftContent;
4
- exports.shiftSetOf = shiftSetOf;
5
- const tslib_1 = require("tslib");
6
- const moment_timezone_1 = tslib_1.__importDefault(require("moment-timezone"));
7
- const shell_1 = require("@things-factory/shell");
8
- function invalid(detail) { throw new shell_1.Refusal('INVALID_SHIFT_CONTENT', {}, detail); }
9
- const clock = (value) => {
10
- if (typeof value !== 'string' || !/^([01]\d|2[0-3]):[0-5]\d(:00)?$/.test(value))
11
- invalid('Use HH:mm with minute precision.');
12
- return String(value).slice(0, 5);
13
- };
14
- const minutes = (value) => Number(value.slice(0, 2)) * 60 + Number(value.slice(3));
15
- /** Weekdays refer to the work date, including shifts starting the previous/next day. */
16
- function shiftDraftContent(input, stored = false) {
17
- if (!input || typeof input !== 'object' || (!stored && Object.keys(input).some(k => !['description', 'timezone', 'shifts', 'effectiveFrom', 'reason'].includes(k))))
18
- invalid('Unexpected shift arrangement fields.');
19
- if (typeof input.timezone !== 'string' || !moment_timezone_1.default.tz.zone(input.timezone))
20
- invalid('Choose an IANA time zone.');
21
- if (!Array.isArray(input.shifts) || !input.shifts.length || input.shifts.length > 64)
22
- invalid('Provide between 1 and 64 shifts.');
23
- const names = new Set(), windows = [];
24
- const shifts = input.shifts.map((row) => {
25
- if (!row || Object.keys(row).some(k => !['name', 'description', 'fromDate', 'fromTime', 'toDate', 'toTime', 'daysOfWeek'].includes(k)))
26
- invalid('Unexpected shift fields.');
27
- const name = typeof row.name === 'string' ? row.name.trim() : '';
28
- if (!name || name.length > 128 || names.has(name))
29
- invalid('Shift names must be nonempty and unique within the arrangement.');
30
- names.add(name);
31
- if (![-1, 0, 1].includes(row.fromDate) || ![-1, 0, 1].includes(row.toDate))
32
- invalid('Date offsets must be -1, 0 or 1.');
33
- const fromTime = clock(row.fromTime), toTime = clock(row.toTime);
34
- const from = row.fromDate * 1440 + minutes(fromTime), to = row.toDate * 1440 + minutes(toTime);
35
- if (to <= from || to - from > 1440)
36
- invalid('A shift must end after it starts and last at most 24 hours.');
37
- const said = row.daysOfWeek ?? '';
38
- if (typeof said !== 'string' || (said !== '' && !/^[0-6](,[0-6])*$/.test(said)))
39
- invalid('Weekdays must be a list of 0 (Sunday) through 6 (Saturday).');
40
- const days = said === '' ? [0, 1, 2, 3, 4, 5, 6] : [...new Set(said.split(',').map(Number))].sort();
41
- for (const day of days)
42
- for (const week of [-1, 0, 1])
43
- windows.push({ from: from + day * 1440 + week * 10080, to: to + day * 1440 + week * 10080, name });
44
- if (row.description != null && typeof row.description !== 'string')
45
- invalid('Shift description must be text.');
46
- return { name, description: row.description ?? '', fromDate: row.fromDate, fromTime, toDate: row.toDate, toTime, daysOfWeek: days.length === 7 ? '' : days.join(',') };
47
- }).sort((a, b) => a.fromDate - b.fromDate || a.fromTime.localeCompare(b.fromTime) || a.name.localeCompare(b.name));
48
- windows.sort((a, b) => a.from - b.from);
49
- for (let i = 1; i < windows.length; i++)
50
- if (windows[i].from < windows[i - 1].to)
51
- invalid(`Shifts overlap: ${windows[i - 1].name}, ${windows[i].name}.`);
52
- if (input.description != null && typeof input.description !== 'string')
53
- invalid('Arrangement description must be text.');
54
- return { description: input.description ?? null, timezone: input.timezone, shifts };
55
- }
56
- /** Every field affecting execution belongs to the signed arrangement. */
57
- function shiftSetOf(shifts) {
58
- return shifts.map(s => ({ name: s.name, description: s.description ?? '', fromDate: s.fromDate,
59
- fromTime: s.fromTime, toDate: s.toDate, toTime: s.toTime, daysOfWeek: s.daysOfWeek ?? '' }))
60
- .sort((a, b) => a.fromDate - b.fromDate || a.fromTime.localeCompare(b.fromTime));
61
- }
62
- //# sourceMappingURL=work-shift-content.js.map