@managemint-solutions/sdk 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -427,6 +427,7 @@ const types = await supabase.leaveTypes.list({ active: true });
|
|
|
427
427
|
const annual = await supabase.leaveTypes.create({ name: 'Annual', description: null, default_days: 15, is_paid: true, requires_approval: true });
|
|
428
428
|
await supabase.leaveTypes.remove(annual.mms_id); // hard delete; 409 once a request or entitlement references it
|
|
429
429
|
|
|
430
|
+
const taken = await supabase.leaveEntitlements.overlaps(userId, annual.mms_id, '2026-01-01', '2026-12-31'); // an entitlement of that type already covers part of the period
|
|
430
431
|
const cover = await supabase.leaveEntitlements.findFor(userId, annual.mms_id, '2026-09-21'); // period + cap, or null = untracked
|
|
431
432
|
const committed = await supabase.leaveRequests.sumDays(userId, annual.mms_id, cover, [LeaveRequestStatus.APPROVED, LeaveRequestStatus.PENDING]);
|
|
432
433
|
const clash = await supabase.leaveRequests.overlaps(userId, '2026-09-21', '2026-09-25');
|
|
@@ -435,6 +436,7 @@ const request = await supabase.leaveRequests.create({ user_id: userId, leave_typ
|
|
|
435
436
|
const reviewed = await supabase.leaveRequests.review(request.mms_id, { status: LeaveReviewDecision.APPROVED, reviewed_by: managerId, review_note: null }); // null = no longer pending
|
|
436
437
|
const cancelled = await supabase.leaveRequests.cancel(request.mms_id, userId); // null = already closed
|
|
437
438
|
const mine = await supabase.leaveRequests.list({ ...query, user_id: me }); // one list; user_id narrows it
|
|
439
|
+
const annualOnly = await supabase.leaveRequests.list({ ...query, leave_type_id: annual.mms_id }); // leave_type_id narrows it too
|
|
438
440
|
const reports = await supabase.leaveRequests.list(query, { userIds: [me, ...(await supabase.users.idsManagedBy(me))] });
|
|
439
441
|
```
|
|
440
442
|
|
|
@@ -443,6 +445,9 @@ the request is still in the status they expect and resolve to `null` otherwise,
|
|
|
443
445
|
cannot both decide the same request. The `leave_requests` table also carries an exclusion
|
|
444
446
|
constraint so two overlapping live requests of one user cannot both be inserted in a race.
|
|
445
447
|
|
|
448
|
+
Notes, additional details and supporting files may attach to leave as well: their `entity`
|
|
449
|
+
accepts `leave_requests` and `leave_entitlements` alongside the CRM entity types.
|
|
450
|
+
|
|
446
451
|
## Public holidays
|
|
447
452
|
|
|
448
453
|
The public-holiday calendar, `public_holidays`, on the caller's client as `supabase.publicHolidays`.
|
package/dist/leave/dto.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export declare class GetLeaveRequestsDto implements GetLeaveRequestsDtoType {
|
|
|
51
51
|
readonly page: number;
|
|
52
52
|
readonly page_size: number;
|
|
53
53
|
readonly user_id?: string | null;
|
|
54
|
+
readonly leave_type_id?: string | null;
|
|
54
55
|
readonly status?: LeaveRequestStatus | null;
|
|
55
56
|
readonly start_date_after?: string | null;
|
|
56
57
|
readonly start_date_before?: string | null;
|
package/dist/leave/dto.js
CHANGED
|
@@ -249,6 +249,7 @@ class GetLeaveRequestsDto {
|
|
|
249
249
|
page = 1;
|
|
250
250
|
page_size = 10;
|
|
251
251
|
user_id;
|
|
252
|
+
leave_type_id;
|
|
252
253
|
status;
|
|
253
254
|
start_date_after;
|
|
254
255
|
start_date_before;
|
|
@@ -275,6 +276,12 @@ __decorate([
|
|
|
275
276
|
(0, class_validator_1.IsUUID)('4', { message: 'Invalid user ID format' }),
|
|
276
277
|
__metadata("design:type", Object)
|
|
277
278
|
], GetLeaveRequestsDto.prototype, "user_id", void 0);
|
|
279
|
+
__decorate([
|
|
280
|
+
(0, class_validator_1.IsOptional)(),
|
|
281
|
+
(0, validators_1.IsNullable)(),
|
|
282
|
+
(0, class_validator_1.IsUUID)('7', { message: 'Invalid leave type ID format' }),
|
|
283
|
+
__metadata("design:type", Object)
|
|
284
|
+
], GetLeaveRequestsDto.prototype, "leave_type_id", void 0);
|
|
278
285
|
__decorate([
|
|
279
286
|
(0, class_validator_1.IsOptional)(),
|
|
280
287
|
(0, validators_1.IsNullable)(),
|
|
@@ -29,6 +29,12 @@ export declare class LeaveEntitlementsResource {
|
|
|
29
29
|
* table's exclusion constraint), so there is at most one.
|
|
30
30
|
*/
|
|
31
31
|
findFor(userId: string, leaveTypeId: string, date: string): Promise<LeaveEntitlementCover | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Whether `userId` already has an entitlement of `leaveTypeId` touching any day of
|
|
34
|
+
* `start`..`end`. The readable half of the rule; the table's exclusion constraint is the half
|
|
35
|
+
* that survives a race. `excludeId` leaves out the entitlement being edited.
|
|
36
|
+
*/
|
|
37
|
+
overlaps(userId: string, leaveTypeId: string, start: string, end: string, excludeId?: string): Promise<boolean>;
|
|
32
38
|
create(input: CreateLeaveEntitlementInput): Promise<LeaveEntitlementEntity>;
|
|
33
39
|
update(leaveEntitlementId: string, input: UpdateLeaveEntitlementDto): Promise<LeaveEntitlementEntity>;
|
|
34
40
|
/** Hard delete: the type simply becomes untracked for that user and period. */
|
|
@@ -94,6 +94,28 @@ class LeaveEntitlementsResource {
|
|
|
94
94
|
const cover = data;
|
|
95
95
|
return { ...cover, days_entitled: Number(cover.days_entitled) };
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether `userId` already has an entitlement of `leaveTypeId` touching any day of
|
|
99
|
+
* `start`..`end`. The readable half of the rule; the table's exclusion constraint is the half
|
|
100
|
+
* that survives a race. `excludeId` leaves out the entitlement being edited.
|
|
101
|
+
*/
|
|
102
|
+
async overlaps(userId, leaveTypeId, start, end, excludeId) {
|
|
103
|
+
let overlapQuery = this.supabase
|
|
104
|
+
.from('leave_entitlements')
|
|
105
|
+
.select('mms_id', { count: 'exact', head: true })
|
|
106
|
+
.eq('organization_id', this.auth.organization_id)
|
|
107
|
+
.eq('user_id', userId)
|
|
108
|
+
.eq('leave_type_id', leaveTypeId)
|
|
109
|
+
.lte('period_start', end)
|
|
110
|
+
.gte('period_end', start);
|
|
111
|
+
if (excludeId) {
|
|
112
|
+
overlapQuery = overlapQuery.neq('mms_id', excludeId);
|
|
113
|
+
}
|
|
114
|
+
const { count, error } = await overlapQuery;
|
|
115
|
+
if (error)
|
|
116
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
117
|
+
return (count ?? 0) > 0;
|
|
118
|
+
}
|
|
97
119
|
async create(input) {
|
|
98
120
|
const row = await this.table.insert({
|
|
99
121
|
user_id: input.user_id,
|
|
@@ -60,6 +60,9 @@ class LeaveRequestsResource {
|
|
|
60
60
|
if (query.user_id) {
|
|
61
61
|
requestsQuery = requestsQuery.eq('user_id', query.user_id);
|
|
62
62
|
}
|
|
63
|
+
if (query.leave_type_id) {
|
|
64
|
+
requestsQuery = requestsQuery.eq('leave_type_id', query.leave_type_id);
|
|
65
|
+
}
|
|
63
66
|
if (query.status) {
|
|
64
67
|
requestsQuery = requestsQuery.eq('status', query.status);
|
|
65
68
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@managemint-solutions/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Typed Supabase data-access SDK for ManageMint Solutions",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Scott Bebington <scottbebington@gmail.com>",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"testEnvironment": "node"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@managemint-solutions/entities": "^1.
|
|
54
|
+
"@managemint-solutions/entities": "^1.22.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@nestjs/common": "^11.0.0",
|