@happyvertical/smrt-human-resources 0.0.0-stage → 0.53.5
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/AGENTS.md +297 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +291 -2
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/dates.d.ts +25 -0
- package/dist/dates.d.ts.map +1 -0
- package/dist/employment/index.d.ts +3 -0
- package/dist/employment/index.d.ts.map +1 -0
- package/dist/employment/models.d.ts +73 -0
- package/dist/employment/models.d.ts.map +1 -0
- package/dist/employment/queries.d.ts +12 -0
- package/dist/employment/queries.d.ts.map +1 -0
- package/dist/employment/service.d.ts +277 -0
- package/dist/employment/service.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2068 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +2424 -0
- package/dist/qualifications/index.d.ts +3 -0
- package/dist/qualifications/index.d.ts.map +1 -0
- package/dist/qualifications/internal.d.ts +24 -0
- package/dist/qualifications/internal.d.ts.map +1 -0
- package/dist/qualifications/models.d.ts +77 -0
- package/dist/qualifications/models.d.ts.map +1 -0
- package/dist/qualifications/service.d.ts +381 -0
- package/dist/qualifications/service.d.ts.map +1 -0
- package/dist/service-base.d.ts +47 -0
- package/dist/service-base.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +902 -0
- package/dist/svelte/components/EmployeeForm.svelte +369 -0
- package/dist/svelte/components/EmployeeForm.svelte.d.ts +28 -0
- package/dist/svelte/components/EmployeeForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/EmployeeList.svelte +158 -0
- package/dist/svelte/components/EmployeeList.svelte.d.ts +13 -0
- package/dist/svelte/components/EmployeeList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte +126 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte.d.ts +13 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PersonQualifications.svelte +156 -0
- package/dist/svelte/components/PersonQualifications.svelte.d.ts +15 -0
- package/dist/svelte/components/PersonQualifications.svelte.d.ts.map +1 -0
- package/dist/svelte/i18n.d.ts +67 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +67 -0
- package/dist/svelte/index.d.ts +23 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +25 -0
- package/dist/svelte/types.d.ts +225 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +257 -0
- package/dist/types.d.ts +119 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +17 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +65 -0
- package/dist/ui.js.map +1 -0
- package/dist/write.d.ts +22 -0
- package/dist/write.d.ts.map +1 -0
- package/package.json +86 -3
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { type EmploymentChangeKind, type EmploymentStatus, type IsoDate, type WorkerType } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* One person's employment with a tenant: the stable record applications and
|
|
5
|
+
* payroll key on. There is one per tenant and profile; a rehire adds an
|
|
6
|
+
* {@link EmploymentTerm} to the same row. The tenant is the employer.
|
|
7
|
+
*
|
|
8
|
+
* Applications extend it with a same-named subclass over the `employments`
|
|
9
|
+
* table that restates the closed surface (see AGENTS.md). Such a subclass may
|
|
10
|
+
* `save()` its own added fields on an existing row; the columns this package
|
|
11
|
+
* owns change only through `EmploymentService`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Employment extends SmrtObject {
|
|
14
|
+
tenantId: string;
|
|
15
|
+
/** The person employed. */
|
|
16
|
+
profileId: string;
|
|
17
|
+
/** Optional login; a worker signing in on a shared device may have none. */
|
|
18
|
+
userId: string | null;
|
|
19
|
+
/** Optional organization profile when it differs from the tenant itself. */
|
|
20
|
+
employerProfileId: string | null;
|
|
21
|
+
/** Free text, unique per tenant. */
|
|
22
|
+
employeeNumber: string;
|
|
23
|
+
workerType: WorkerType;
|
|
24
|
+
/** Position or trade label; latest recorded value. */
|
|
25
|
+
position: string | null;
|
|
26
|
+
status: EmploymentStatus;
|
|
27
|
+
save(): Promise<this>;
|
|
28
|
+
delete(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One continuous period of employment. `endedOn` is the last day employed
|
|
32
|
+
* (inclusive); null means the term is open. "Employed on a date" is answered
|
|
33
|
+
* from terms, never from {@link Employment.status}.
|
|
34
|
+
*/
|
|
35
|
+
export declare class EmploymentTerm extends SmrtObject {
|
|
36
|
+
tenantId: string;
|
|
37
|
+
employmentId: string;
|
|
38
|
+
startedOn: IsoDate;
|
|
39
|
+
endedOn: IsoDate | null;
|
|
40
|
+
endReason: string;
|
|
41
|
+
save(): Promise<this>;
|
|
42
|
+
delete(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/** Append-only dated change to an employment, attributed to an actor. */
|
|
45
|
+
export declare class EmploymentChange extends SmrtObject {
|
|
46
|
+
tenantId: string;
|
|
47
|
+
employmentId: string;
|
|
48
|
+
kind: EmploymentChangeKind;
|
|
49
|
+
effectiveOn: IsoDate;
|
|
50
|
+
fromValue: string | null;
|
|
51
|
+
toValue: string | null;
|
|
52
|
+
note: string;
|
|
53
|
+
actorProfileId: string;
|
|
54
|
+
save(): Promise<this>;
|
|
55
|
+
delete(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Scoped persistence collection; mutations must use EmploymentService.
|
|
59
|
+
* Collections are registered too, so each restates the closed surface: an
|
|
60
|
+
* undecorated one would publish its methods as generated tools.
|
|
61
|
+
*/
|
|
62
|
+
export declare class EmploymentCollection extends SmrtCollection<Employment> {
|
|
63
|
+
static readonly _itemClass: typeof Employment;
|
|
64
|
+
}
|
|
65
|
+
/** Scoped term collection; closed like its model. */
|
|
66
|
+
export declare class EmploymentTermCollection extends SmrtCollection<EmploymentTerm> {
|
|
67
|
+
static readonly _itemClass: typeof EmploymentTerm;
|
|
68
|
+
}
|
|
69
|
+
/** Scoped append-only change collection; closed like its model. */
|
|
70
|
+
export declare class EmploymentChangeCollection extends SmrtCollection<EmploymentChange> {
|
|
71
|
+
static readonly _itemClass: typeof EmploymentChange;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/employment/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAErB,KAAK,OAAO,EACZ,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAerB;;;;;;;;;GASG;AACH,qBAiBa,UAAW,SAAQ,UAAU;IAC5B,QAAQ,SAAM;IAC1B,2BAA2B;IAI3B,SAAS,SAAM;IACf,4EAA4E;IAE5E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7B,4EAA4E;IAK5E,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxC,oCAAoC;IACpC,cAAc,SAAM;IACK,UAAU,EAAE,UAAU,CAAc;IAC7D,sDAAsD;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/C,MAAM,EAAE,gBAAgB,CAAY;IAE9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC;AAED;;;;GAIG;AACH,qBAca,cAAe,SAAQ,UAAU;IAChC,QAAQ,SAAM;IAC0B,YAAY,SAAM;IAC7C,SAAS,EAAE,OAAO,CAAM;IACR,OAAO,EAAE,OAAO,GAAG,IAAI,CAAQ;IACxE,SAAS,SAAM;IAEA,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC;AAED,yEAAyE;AACzE,qBAca,gBAAiB,SAAQ,UAAU;IAClC,QAAQ,SAAM;IAC0B,YAAY,SAAM;IAC7C,IAAI,EAAE,oBAAoB,CAAW;IACrC,WAAW,EAAE,OAAO,CAAM;IACV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IACvE,IAAI,SAAM;IAIV,cAAc,SAAM;IAEL,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC;AAED;;;;GAIG;AACH,qBACa,oBAAqB,SAAQ,cAAc,CAAC,UAAU,CAAC;IAClE,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;CACzC;AACD,qDAAqD;AACrD,qBACa,wBAAyB,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1E,MAAM,CAAC,QAAQ,CAAC,UAAU,wBAAkB;CAC7C;AACD,mEAAmE;AACnE,qBACa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;CAC/C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/sql';
|
|
2
|
+
import type { IsoDate } from '../types.js';
|
|
3
|
+
import { type Employment, type EmploymentTerm } from './models.js';
|
|
4
|
+
/**
|
|
5
|
+
* Terms that cover `on` for one tenant. Run inside the tenant's scope; the
|
|
6
|
+
* caller supplies a validated date. Shared by both services so "employed on a
|
|
7
|
+
* date" has one definition.
|
|
8
|
+
*/
|
|
9
|
+
export declare function termsCovering(db: DatabaseInterface, tenantId: string, on: IsoDate): Promise<EmploymentTerm[]>;
|
|
10
|
+
/** Employments with a term covering `on`, for one tenant. */
|
|
11
|
+
export declare function employmentsOn(db: DatabaseInterface, tenantId: string, on: IsoDate): Promise<Employment[]>;
|
|
12
|
+
//# sourceMappingURL=queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/employment/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,KAAK,UAAU,EAEf,KAAK,cAAc,EAEpB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,OAAO,GACV,OAAO,CAAC,cAAc,EAAE,CAAC,CAM3B;AAED,6DAA6D;AAC7D,wBAAsB,aAAa,CACjC,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,OAAO,GACV,OAAO,CAAC,UAAU,EAAE,CAAC,CASvB"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { HrService } from '../service-base.js';
|
|
2
|
+
import { type EmploymentCheck, type IsoDate, type WorkerType } from '../types.js';
|
|
3
|
+
import { Employment, EmploymentChange, EmploymentTerm } from './models.js';
|
|
4
|
+
/** Input to {@link EmploymentService.hire}. */
|
|
5
|
+
export interface HireInput {
|
|
6
|
+
/** The person being employed (`smrt-profiles:Profile` id). */
|
|
7
|
+
profileId: string;
|
|
8
|
+
/** Free text, unique per tenant; surrounding whitespace is trimmed. */
|
|
9
|
+
employeeNumber: string;
|
|
10
|
+
/** First day employed. */
|
|
11
|
+
startedOn: IsoDate;
|
|
12
|
+
/** Lowercase kebab-case; defaults to `employee`. */
|
|
13
|
+
workerType?: WorkerType;
|
|
14
|
+
/** Position or trade label; blank means none. */
|
|
15
|
+
position?: string | null;
|
|
16
|
+
/** Optional login (`smrt-users:User` id). */
|
|
17
|
+
userId?: string | null;
|
|
18
|
+
/** Optional organization profile when it differs from the tenant itself. */
|
|
19
|
+
employerProfileId?: string | null;
|
|
20
|
+
}
|
|
21
|
+
/** Input to {@link EmploymentService.end}. */
|
|
22
|
+
export interface EndEmploymentInput {
|
|
23
|
+
/** The last day employed, inclusive. */
|
|
24
|
+
endedOn: IsoDate;
|
|
25
|
+
/** Free-text reason kept on the closed term and the change row. */
|
|
26
|
+
reason?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Input to {@link EmploymentService.rehire}. */
|
|
29
|
+
export interface RehireInput {
|
|
30
|
+
/** First day of the new term; must be after the previous term's last day. */
|
|
31
|
+
startedOn: IsoDate;
|
|
32
|
+
/** New worker type; omitted keeps the previous one. */
|
|
33
|
+
workerType?: WorkerType;
|
|
34
|
+
/** New position (null clears it); omitted keeps the previous one. */
|
|
35
|
+
position?: string | null;
|
|
36
|
+
}
|
|
37
|
+
/** Input to {@link EmploymentService.changePosition}. */
|
|
38
|
+
export interface ChangePositionInput {
|
|
39
|
+
/** The new position; null or blank clears it. */
|
|
40
|
+
position: string | null;
|
|
41
|
+
/** The day the new position takes effect. */
|
|
42
|
+
effectiveOn: IsoDate;
|
|
43
|
+
/** Optional note kept on the change row. */
|
|
44
|
+
note?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Input to {@link EmploymentService.changeWorkerType}. */
|
|
47
|
+
export interface ChangeWorkerTypeInput {
|
|
48
|
+
/** The new worker type, lowercase kebab-case. */
|
|
49
|
+
workerType: WorkerType;
|
|
50
|
+
/** The day the new worker type takes effect. */
|
|
51
|
+
effectiveOn: IsoDate;
|
|
52
|
+
/** Optional note kept on the change row. */
|
|
53
|
+
note?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Input to {@link EmploymentService.placeOnLeave} and {@link EmploymentService.returnFromLeave}. */
|
|
56
|
+
export interface LeaveInput {
|
|
57
|
+
/** The first day of leave, or the first day back. */
|
|
58
|
+
effectiveOn: IsoDate;
|
|
59
|
+
/** Optional note kept on the change row. */
|
|
60
|
+
note?: string;
|
|
61
|
+
}
|
|
62
|
+
/** Input to {@link EmploymentService.linkLogin} and {@link EmploymentService.unlinkLogin}. */
|
|
63
|
+
export interface LoginLinkInput {
|
|
64
|
+
/**
|
|
65
|
+
* The date recorded on the change row. It does not schedule anything: the
|
|
66
|
+
* link or unlink takes effect as soon as it is recorded.
|
|
67
|
+
*/
|
|
68
|
+
effectiveOn: IsoDate;
|
|
69
|
+
}
|
|
70
|
+
/** An employment's recorded state on one calendar date. */
|
|
71
|
+
export interface EmploymentAsOf {
|
|
72
|
+
/** Position in effect on the date; before any change, the position at hire. */
|
|
73
|
+
position: string | null;
|
|
74
|
+
/** Worker type in effect on the date; before any change, the type at hire. */
|
|
75
|
+
workerType: string;
|
|
76
|
+
/** Whether a term covers the date. */
|
|
77
|
+
employed: boolean;
|
|
78
|
+
/** Whether the person was employed and on leave on the date. */
|
|
79
|
+
onLeave: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The only writer of employment records. Construct it from a trusted
|
|
83
|
+
* `{ tenantId, profileId }` actor the application has already authorized.
|
|
84
|
+
* Every mutation runs in one transaction, appends a dated
|
|
85
|
+
* {@link EmploymentChange} attributed to the actor, and delivers its event
|
|
86
|
+
* after the transaction commits. Dates are calendar dates (`YYYY-MM-DD`).
|
|
87
|
+
*/
|
|
88
|
+
export declare class EmploymentService extends HrService {
|
|
89
|
+
private load;
|
|
90
|
+
private one;
|
|
91
|
+
private termsOf;
|
|
92
|
+
private changesOf;
|
|
93
|
+
/**
|
|
94
|
+
* Append a change. Creation instants are strictly increasing within one
|
|
95
|
+
* employment (writes are serialized per tenant), so same-day changes replay
|
|
96
|
+
* in the order they were recorded.
|
|
97
|
+
*/
|
|
98
|
+
private record;
|
|
99
|
+
/**
|
|
100
|
+
* The term a dated change belongs to, with `effectiveOn` inside it: the
|
|
101
|
+
* latest term, which is the open one until an end is recorded and the final
|
|
102
|
+
* one (up to its last day) afterwards. The stored status plays no part, so
|
|
103
|
+
* a change dated inside a notice period is accepted.
|
|
104
|
+
*
|
|
105
|
+
* @throws HrError `HR_INVALID` before the term started, `HR_STATUS_TRANSITION` after its last day
|
|
106
|
+
*/
|
|
107
|
+
private latestTerm;
|
|
108
|
+
private notBeforeLatest;
|
|
109
|
+
/**
|
|
110
|
+
* A login is exclusive to the employment that stores it until it is
|
|
111
|
+
* explicitly unlinked there, whatever that employment's stored status. An
|
|
112
|
+
* ended employment keeps its login through its notice period and after, so
|
|
113
|
+
* two employments never share one and `findByUser(userId, on)` cannot be
|
|
114
|
+
* ambiguous through the service.
|
|
115
|
+
*/
|
|
116
|
+
private loginFree;
|
|
117
|
+
private transition;
|
|
118
|
+
/**
|
|
119
|
+
* Employ a person: creates the employment, its first term and a `hired`
|
|
120
|
+
* change. A profile has one employment per tenant, so a person who worked
|
|
121
|
+
* here before is rehired instead.
|
|
122
|
+
*
|
|
123
|
+
* @throws HrError `HR_ALREADY_EMPLOYED`, `HR_EMPLOYEE_NUMBER_TAKEN`, `HR_INVALID` (including a login already linked to another employment, ended or not: unlink it there first)
|
|
124
|
+
*/
|
|
125
|
+
hire(input: HireInput): Promise<Employment>;
|
|
126
|
+
/**
|
|
127
|
+
* End an employment: closes the open term on `endedOn` (the last day
|
|
128
|
+
* employed, inclusive) and, in the same transaction, revokes its
|
|
129
|
+
* employment-scoped qualifications from the day after, so they are still
|
|
130
|
+
* good on the last day. `endedOn` cannot be earlier than a position,
|
|
131
|
+
* worker-type or leave change already recorded in the term.
|
|
132
|
+
*
|
|
133
|
+
* `endedOn` may be ahead of the day the end is recorded (a notice period).
|
|
134
|
+
* The stored status becomes `ended` at once, meaning "an end has been
|
|
135
|
+
* recorded": the person is still employed up to and including `endedOn`,
|
|
136
|
+
* so ask by date with {@link check}, {@link employedOn}, {@link asOf} or
|
|
137
|
+
* `findByUser(userId, on)`. Position, worker-type and leave changes dated
|
|
138
|
+
* inside the final term are still accepted.
|
|
139
|
+
*
|
|
140
|
+
* @throws HrError `HR_STATUS_TRANSITION` when already ended, `HR_INVALID`, `HR_NOT_FOUND`
|
|
141
|
+
*/
|
|
142
|
+
end(employmentId: string, input: EndEmploymentInput): Promise<Employment>;
|
|
143
|
+
/**
|
|
144
|
+
* Rehire an ended employment: adds a term to the same row, so the
|
|
145
|
+
* employment id stays stable. The new term cannot start before a position,
|
|
146
|
+
* worker-type or leave change already recorded. The employment keeps the
|
|
147
|
+
* login it stored, which no other employment can have taken meanwhile.
|
|
148
|
+
*
|
|
149
|
+
* @throws HrError `HR_STATUS_TRANSITION` unless ended, `HR_TERM_OVERLAP`, `HR_INVALID`, `HR_NOT_FOUND`
|
|
150
|
+
*/
|
|
151
|
+
rehire(employmentId: string, input: RehireInput): Promise<Employment>;
|
|
152
|
+
/**
|
|
153
|
+
* Record a new position from `effectiveOn`. The employment row holds the
|
|
154
|
+
* latest value; the change row carries the old and new ones.
|
|
155
|
+
*
|
|
156
|
+
* `effectiveOn` must fall inside the latest term. Once an end has been
|
|
157
|
+
* recorded that is the final term, up to and including its `endedOn`, so a
|
|
158
|
+
* change during a notice period is accepted; the stored status stays
|
|
159
|
+
* `ended`.
|
|
160
|
+
*
|
|
161
|
+
* @throws HrError `HR_STATUS_TRANSITION` when `effectiveOn` is after the last day of an ended employment; `HR_INVALID` for a no-op, a date before the term started or before the latest position change; `HR_NOT_FOUND`
|
|
162
|
+
*/
|
|
163
|
+
changePosition(employmentId: string, input: ChangePositionInput): Promise<Employment>;
|
|
164
|
+
/**
|
|
165
|
+
* Record a new worker type from `effectiveOn`. The employment row holds the
|
|
166
|
+
* latest value; the change row carries the old and new ones.
|
|
167
|
+
*
|
|
168
|
+
* `effectiveOn` must fall inside the latest term. Once an end has been
|
|
169
|
+
* recorded that is the final term, up to and including its `endedOn`, so a
|
|
170
|
+
* change during a notice period is accepted; the stored status stays
|
|
171
|
+
* `ended`.
|
|
172
|
+
*
|
|
173
|
+
* @throws HrError `HR_STATUS_TRANSITION` when `effectiveOn` is after the last day of an ended employment; `HR_INVALID` for a no-op, a bad value, a date before the term started or before the latest worker-type change; `HR_NOT_FOUND`
|
|
174
|
+
*/
|
|
175
|
+
changeWorkerType(employmentId: string, input: ChangeWorkerTypeInput): Promise<Employment>;
|
|
176
|
+
private leave;
|
|
177
|
+
/**
|
|
178
|
+
* Place an employment on leave from `effectiveOn`. A person on leave is
|
|
179
|
+
* still employed.
|
|
180
|
+
*
|
|
181
|
+
* Once an end has been recorded, leave dated inside the final term (up to
|
|
182
|
+
* and including its `endedOn`) is still accepted: it is recorded as a
|
|
183
|
+
* change row, the stored status stays `ended`, and whether the person is
|
|
184
|
+
* already on leave is decided by replaying the history as of `effectiveOn`.
|
|
185
|
+
*
|
|
186
|
+
* @throws HrError `HR_STATUS_TRANSITION` when already on leave, or when `effectiveOn` is after the last day of an ended employment; `HR_INVALID` for a date before the term started or before the latest leave change; `HR_NOT_FOUND`
|
|
187
|
+
*/
|
|
188
|
+
placeOnLeave(employmentId: string, input: LeaveInput): Promise<Employment>;
|
|
189
|
+
/**
|
|
190
|
+
* Return an employment from leave; `effectiveOn` is the first day back.
|
|
191
|
+
*
|
|
192
|
+
* Once an end has been recorded, a return dated inside the final term (up
|
|
193
|
+
* to and including its `endedOn`) is still accepted: it is recorded as a
|
|
194
|
+
* change row, the stored status stays `ended`, and whether the person is
|
|
195
|
+
* on leave is decided by replaying the history as of `effectiveOn`.
|
|
196
|
+
*
|
|
197
|
+
* @throws HrError `HR_STATUS_TRANSITION` unless on leave, or when `effectiveOn` is after the last day of an ended employment; `HR_INVALID` for a date before the term started or before the latest leave change; `HR_NOT_FOUND`
|
|
198
|
+
*/
|
|
199
|
+
returnFromLeave(employmentId: string, input: LeaveInput): Promise<Employment>;
|
|
200
|
+
private login;
|
|
201
|
+
/**
|
|
202
|
+
* Link a login (`smrt-users:User` id) to an employment, replacing any
|
|
203
|
+
* previous one. Grants nothing by itself: permissions stay with smrt-users.
|
|
204
|
+
* A login belongs to one employment at a time and stays with it, ended or
|
|
205
|
+
* not, until {@link unlinkLogin} clears it there.
|
|
206
|
+
*
|
|
207
|
+
* The link takes effect at once, whatever `effectiveOn` says: the date is
|
|
208
|
+
* only recorded on the change row, and login links are not replayed by
|
|
209
|
+
* {@link asOf} or `findByUser(userId, on)`.
|
|
210
|
+
*
|
|
211
|
+
* @throws HrError `HR_INVALID` when already linked to this login, or to another employment (unlink it there first); `HR_NOT_FOUND`
|
|
212
|
+
*/
|
|
213
|
+
linkLogin(employmentId: string, userId: string, input: LoginLinkInput): Promise<Employment>;
|
|
214
|
+
/**
|
|
215
|
+
* Clear an employment's login, which frees it for another employment. Works
|
|
216
|
+
* on an ended employment too. The login is cleared at once, whatever
|
|
217
|
+
* `effectiveOn` says; a future date does not keep it linked until then.
|
|
218
|
+
*
|
|
219
|
+
* @throws HrError `HR_INVALID` when no login is linked, `HR_NOT_FOUND`
|
|
220
|
+
*/
|
|
221
|
+
unlinkLogin(employmentId: string, input: LoginLinkInput): Promise<Employment>;
|
|
222
|
+
/**
|
|
223
|
+
* One employment in the actor's tenant.
|
|
224
|
+
*
|
|
225
|
+
* @throws HrError `HR_NOT_FOUND` when it does not exist in this tenant
|
|
226
|
+
*/
|
|
227
|
+
get(employmentId: string): Promise<Employment>;
|
|
228
|
+
/** The profile's employment in this tenant (ended or not), or null. */
|
|
229
|
+
findByProfile(profileId: string): Promise<Employment | null>;
|
|
230
|
+
/** The employment with this employee number in this tenant, or null. */
|
|
231
|
+
findByEmployeeNumber(employeeNumber: string): Promise<Employment | null>;
|
|
232
|
+
/**
|
|
233
|
+
* The employment linked to a login. Fails closed: null when there is none,
|
|
234
|
+
* or when more than one matches (the service keeps a login on one
|
|
235
|
+
* employment, so that takes rows written some other way).
|
|
236
|
+
*
|
|
237
|
+
* With `on`, the answer comes from the dated terms: the employment linked
|
|
238
|
+
* to the login that has a term covering `on`, whatever its stored status.
|
|
239
|
+
* Without `on`, it is the linked employment whose stored status is not
|
|
240
|
+
* `ended`, which stops resolving as soon as an end is recorded. A host that
|
|
241
|
+
* records end dates ahead of time (a notice period) should pass the date,
|
|
242
|
+
* or the worker is locked out before their last day.
|
|
243
|
+
*
|
|
244
|
+
* @throws HrError `HR_INVALID` when `on` is given and is not a calendar date
|
|
245
|
+
*/
|
|
246
|
+
findByUser(userId: string, on?: IsoDate): Promise<Employment | null>;
|
|
247
|
+
/** Everyone with a term covering `on`, including people on leave. */
|
|
248
|
+
employedOn(on: IsoDate): Promise<Employment[]>;
|
|
249
|
+
/**
|
|
250
|
+
* Whether a profile is employed on a date. Answered from terms, never from
|
|
251
|
+
* the stored status; `onLeave` is computed as of `on`, so past dates answer
|
|
252
|
+
* correctly.
|
|
253
|
+
*/
|
|
254
|
+
check(profileId: string, on: IsoDate): Promise<EmploymentCheck>;
|
|
255
|
+
/**
|
|
256
|
+
* An employment's terms, oldest first.
|
|
257
|
+
*
|
|
258
|
+
* @throws HrError `HR_NOT_FOUND` when the employment is not in this tenant
|
|
259
|
+
*/
|
|
260
|
+
terms(employmentId: string): Promise<EmploymentTerm[]>;
|
|
261
|
+
/**
|
|
262
|
+
* An employment's dated changes, by effective date and then in the order
|
|
263
|
+
* they were recorded.
|
|
264
|
+
*
|
|
265
|
+
* @throws HrError `HR_NOT_FOUND` when the employment is not in this tenant
|
|
266
|
+
*/
|
|
267
|
+
history(employmentId: string): Promise<EmploymentChange[]>;
|
|
268
|
+
/**
|
|
269
|
+
* An employment's position, worker type and standing on one date, replayed
|
|
270
|
+
* from the change history. Before the first term the values are those at
|
|
271
|
+
* hire and `employed` is false.
|
|
272
|
+
*
|
|
273
|
+
* @throws HrError `HR_NOT_FOUND` when the employment is not in this tenant
|
|
274
|
+
*/
|
|
275
|
+
asOf(employmentId: string, on: IsoDate): Promise<EmploymentAsOf>;
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/employment/service.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-human-resources
|
|
3
|
+
*
|
|
4
|
+
* HR records: who works for an organization, as what, and with what standing.
|
|
5
|
+
* Employment (one record per tenant and profile, with dated terms and an
|
|
6
|
+
* append-only change history) and qualifications (definitions, and what each
|
|
7
|
+
* person holds, with expiry). Pay, time records, logins and identity live in
|
|
8
|
+
* other packages.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import './__smrt-register__.js';
|
|
13
|
+
export { addDays, addMonths, assertIsoDate, isIsoDate } from './dates.js';
|
|
14
|
+
export * from './employment/index.js';
|
|
15
|
+
export * from './qualifications/index.js';
|
|
16
|
+
export { EMPLOYMENT_STATUS_TRANSITIONS, type EmploymentChangeKind, type EmploymentCheck, type EmploymentEventType, type EmploymentStatus, type HeldQualificationChangeKind, type HeldQualificationEventType, type HeldQualificationStatus, type HrActor, HrError, type HrErrorCode, type HrEvent, type HrEventHandler, type HrServiceOptions, type IsoDate, type QualificationCheck, type QualificationKind, type QualificationScope, SUGGESTED_WORKER_TYPES, type WorkerType, } from './types.js';
|
|
17
|
+
export { HUMAN_RESOURCES_MODULE_META, HUMAN_RESOURCES_UI_SLOTS, } from './ui.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC1E,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,6BAA6B,EAC7B,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,OAAO,EACZ,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,SAAS,CAAC"}
|