@fabriktor/fx 0.0.124 → 0.0.126
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BillableOperator, PayrollsOperator, QueryOptions } from "@fabriktor/client";
|
|
2
|
-
import { ColPayrollsPayrolls, ColPayrollsHourBanks, ColPayrollsPayables, ColPayrollsAdjustments, ColPayrollsAdjustmentFolders, ColPayrollsPayConfigs, ColPayrollsEmployeePayConfigs, ColPayrollsAdjustmentRecords, ColPayrollsAdjustmentAggregates, ColPayrollsPayrollPrograms, type Payroll, type HourBank, type Payable, type Adjustment, type AdjustmentFolder, type PayConfig, type EmployeePayConfig, type AdjustmentRecord, type AdjustmentAggregate, type PayrollProgram, type InPayroll, type InAdjustment, type InAdjustmentFolder, type InPayConfig, type InEmployeePayConfig, type InPayrollProgram, type InAdjustmentAggregate, type PLPayrollsGeneratePayrollFromEntities, type InDate, type Period } from "@fabriktor/schema";
|
|
1
|
+
import type { FieldOf, BillableOperator, PayrollsOperator, QueryOptions } from "@fabriktor/client";
|
|
2
|
+
import { ColPayrollsPayrolls, ColPayrollsHourBanks, ColPayrollsPayables, ColPayrollsAdjustments, ColPayrollsAdjustmentFolders, ColPayrollsPayConfigs, ColPayrollsEmployeePayConfigs, ColPayrollsAdjustmentRecords, ColPayrollsAdjustmentAggregates, ColPayrollsPayrollPrograms, type Payroll, type HourBank, type Payable, type Adjustment, type AdjustmentFolder, type PayConfig, type EmployeePayConfig, type AdjustmentRecord, type AdjustmentAggregate, type PayrollProgram, type InPayroll, type InAdjustment, type InAdjustmentFolder, type InPayConfig, type InEmployeePayConfig, type InPayrollProgram, type InAdjustmentAggregate, type PLPayrollsGeneratePayrollFromEntities, type InDate, type Period, type Folder } from "@fabriktor/schema";
|
|
3
3
|
import type { EmploymentActor, EmploymentReadContext } from "../contacts/scope.js";
|
|
4
4
|
import { type SearchOptions, type SearchPage } from "../core/search.js";
|
|
5
5
|
import type { MultiCreateAttempt } from "../core/multi-create.js";
|
|
@@ -49,98 +49,19 @@ export type PayrollFilters = {
|
|
|
49
49
|
type?: string[];
|
|
50
50
|
name?: string[];
|
|
51
51
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
archive: boolean;
|
|
61
|
-
};
|
|
62
|
-
hour_banks: {
|
|
63
|
-
searchable: false;
|
|
64
|
-
filters: ("timezone" | "currency" | "employee_id" | "period_indexes" | "is_payrolled")[];
|
|
65
|
-
employee_read: boolean;
|
|
66
|
-
create: boolean;
|
|
67
|
-
archive: boolean;
|
|
68
|
-
remove: boolean;
|
|
69
|
-
report: boolean;
|
|
70
|
-
};
|
|
71
|
-
payables: {
|
|
72
|
-
filters: ("period_index" | "currency" | "employee_id" | "payroll_id" | "is_payrolled")[];
|
|
73
|
-
employee_read: boolean;
|
|
74
|
-
searchable: boolean;
|
|
75
|
-
create: boolean;
|
|
76
|
-
archive: boolean;
|
|
77
|
-
remove: boolean;
|
|
78
|
-
report: boolean;
|
|
79
|
-
};
|
|
80
|
-
adjustments: {
|
|
81
|
-
filters: ("is_archived" | "type" | "currency" | "folder_id" | "name" | "is_employer_contribution")[];
|
|
82
|
-
employee_read: boolean;
|
|
83
|
-
searchable: boolean;
|
|
84
|
-
create: boolean;
|
|
85
|
-
archive: boolean;
|
|
86
|
-
remove: boolean;
|
|
87
|
-
report: boolean;
|
|
88
|
-
};
|
|
89
|
-
adjustment_folders: {
|
|
90
|
-
filters: "is_archived"[];
|
|
91
|
-
employee_read: boolean;
|
|
92
|
-
searchable: boolean;
|
|
93
|
-
create: boolean;
|
|
94
|
-
archive: boolean;
|
|
95
|
-
remove: boolean;
|
|
96
|
-
report: boolean;
|
|
97
|
-
};
|
|
98
|
-
pay_configs: {
|
|
99
|
-
filters: ("is_archived" | "type" | "currency" | "name")[];
|
|
100
|
-
employee_read: boolean;
|
|
101
|
-
searchable: boolean;
|
|
102
|
-
create: boolean;
|
|
103
|
-
archive: boolean;
|
|
104
|
-
remove: boolean;
|
|
105
|
-
report: boolean;
|
|
106
|
-
};
|
|
107
|
-
employee_pay_configs: {
|
|
108
|
-
employee_read: true;
|
|
109
|
-
filters: ("is_archived" | "currency" | "name" | "employee_id" | "pay_config_id")[];
|
|
110
|
-
searchable: boolean;
|
|
111
|
-
create: boolean;
|
|
112
|
-
archive: boolean;
|
|
113
|
-
remove: boolean;
|
|
114
|
-
report: boolean;
|
|
115
|
-
};
|
|
116
|
-
adjustment_records: {
|
|
117
|
-
filters: ("period_index" | "currency" | "employee_id" | "payroll_id")[];
|
|
118
|
-
employee_read: boolean;
|
|
119
|
-
searchable: boolean;
|
|
120
|
-
create: boolean;
|
|
121
|
-
archive: boolean;
|
|
122
|
-
remove: boolean;
|
|
123
|
-
report: boolean;
|
|
124
|
-
};
|
|
125
|
-
adjustment_aggregates: {
|
|
126
|
-
employee_read: false;
|
|
127
|
-
create: true;
|
|
128
|
-
report: true;
|
|
129
|
-
filters: ("currency" | "period_indexes")[];
|
|
130
|
-
searchable: boolean;
|
|
131
|
-
archive: boolean;
|
|
132
|
-
remove: boolean;
|
|
133
|
-
};
|
|
134
|
-
payroll_programs: {
|
|
135
|
-
searchable: false;
|
|
136
|
-
create: true;
|
|
137
|
-
remove: true;
|
|
138
|
-
filters: ("timezone" | "currency" | "employee_id" | "employee_pay_config_id" | "is_enabled")[];
|
|
139
|
-
employee_read: boolean;
|
|
140
|
-
archive: boolean;
|
|
141
|
-
report: boolean;
|
|
142
|
-
};
|
|
52
|
+
type Policy<K extends PayrollResource> = {
|
|
53
|
+
employee_read: boolean;
|
|
54
|
+
searchable: boolean;
|
|
55
|
+
create: boolean;
|
|
56
|
+
archive: boolean;
|
|
57
|
+
remove: boolean;
|
|
58
|
+
report: boolean;
|
|
59
|
+
filters: readonly (keyof PayrollFilters & FieldOf<PayrollRecordMap[K]>)[];
|
|
143
60
|
};
|
|
61
|
+
type PayrollPolicies = {
|
|
62
|
+
[K in PayrollResource]: Policy<K>;
|
|
63
|
+
};
|
|
64
|
+
export declare const payrollPolicies: PayrollPolicies;
|
|
144
65
|
export declare const payrollPayTypes: readonly ["per_hour", "fixed"];
|
|
145
66
|
export declare const payrollAdjustmentTypes: readonly ["rate", "per_period", "per_hour"];
|
|
146
67
|
export declare const payrollRecurrenceTypes: readonly ["daily", "weekly", "monthly", "yearly"];
|
|
@@ -182,7 +103,7 @@ export declare class PayrollWorkflowError extends Error {
|
|
|
182
103
|
}
|
|
183
104
|
export declare function payrollCanManage(actor: EmploymentActor, record?: PayrollRecord | null): boolean;
|
|
184
105
|
export declare function payrollCanRead(actor: EmploymentActor, resource: PayrollResource): boolean;
|
|
185
|
-
export declare function payrollFilterQuery(resource:
|
|
106
|
+
export declare function payrollFilterQuery<K extends PayrollResource>(resource: K, filters?: PayrollFilters, employee_id?: string): QueryOptions;
|
|
186
107
|
export declare class PayrollsWorkspace {
|
|
187
108
|
private readonly payrolls;
|
|
188
109
|
private readonly billable?;
|
|
@@ -204,7 +125,9 @@ export declare class PayrollsWorkspace {
|
|
|
204
125
|
private adjustments;
|
|
205
126
|
private config;
|
|
206
127
|
private validateCommand;
|
|
128
|
+
updateFolder(actor: EmploymentActor, id: string, input: Folder): Promise<AdjustmentFolder>;
|
|
207
129
|
setArchived(actor: EmploymentActor, resource: PayrollResource, record: PayrollRecord, value: boolean): Promise<void>;
|
|
208
130
|
setEnabled(actor: EmploymentActor, record: PayrollProgram, is_enabled: boolean): Promise<void>;
|
|
209
131
|
remove(actor: EmploymentActor, resource: PayrollResource, record: PayrollRecord): Promise<void>;
|
|
210
132
|
}
|
|
133
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isHTTPClientErr } from "@fabriktor/client";
|
|
1
|
+
import { isHTTPClientErr, queryParam } from "@fabriktor/client";
|
|
2
2
|
import { ColPayrollsPayrolls, ColPayrollsHourBanks, ColPayrollsPayables, ColPayrollsAdjustments, ColPayrollsAdjustmentFolders, ColPayrollsPayConfigs, ColPayrollsEmployeePayConfigs, ColPayrollsAdjustmentRecords, ColPayrollsAdjustmentAggregates, ColPayrollsPayrollPrograms, UserTypeEmployer, UserTypeEmployee, AdjustmentTypeRate, AdjustmentTypePerHour, AdjustmentTypePerPeriod, PayTypeFixed, PayTypePerHour, RecurrenceTypeDaily, RecurrenceTypeWeekly, RecurrenceTypeMonthly, RecurrenceTypeYearly, } from "@fabriktor/schema";
|
|
3
3
|
import { employmentCanRead, employmentCatalogOwnerIDs, employmentOwnsRecord, } from "../contacts/scope.js";
|
|
4
4
|
import { normalizeIDs, requiredOperationID } from "../core/id.js";
|
|
@@ -23,7 +23,6 @@ const generated = {
|
|
|
23
23
|
archive: false,
|
|
24
24
|
remove: false,
|
|
25
25
|
report: false,
|
|
26
|
-
filters: [],
|
|
27
26
|
};
|
|
28
27
|
const catalog = {
|
|
29
28
|
...generated,
|
|
@@ -31,7 +30,7 @@ const catalog = {
|
|
|
31
30
|
create: true,
|
|
32
31
|
archive: true,
|
|
33
32
|
};
|
|
34
|
-
//
|
|
33
|
+
// Service routes, record behavior and Rules() define this capability/filter table.
|
|
35
34
|
// A generic CRUD method in the client is not permission to edit an immutable record.
|
|
36
35
|
export const payrollPolicies = {
|
|
37
36
|
[PayrollResource.Payrolls]: {
|
|
@@ -82,7 +81,12 @@ export const payrollPolicies = {
|
|
|
82
81
|
"is_archived",
|
|
83
82
|
],
|
|
84
83
|
},
|
|
85
|
-
[PayrollResource.Folders]: {
|
|
84
|
+
[PayrollResource.Folders]: {
|
|
85
|
+
...catalog,
|
|
86
|
+
archive: false,
|
|
87
|
+
remove: true,
|
|
88
|
+
filters: ["is_archived"],
|
|
89
|
+
},
|
|
86
90
|
[PayrollResource.PayConfigs]: {
|
|
87
91
|
...catalog,
|
|
88
92
|
filters: ["type", "name", "currency", "is_archived"],
|
|
@@ -162,9 +166,18 @@ export function payrollCanRead(actor, resource) {
|
|
|
162
166
|
(actor.active_mode === UserTypeEmployer ||
|
|
163
167
|
payrollPolicies[resource].employee_read));
|
|
164
168
|
}
|
|
165
|
-
export function payrollFilterQuery(resource, filters = {}) {
|
|
166
|
-
const
|
|
167
|
-
|
|
169
|
+
export function payrollFilterQuery(resource, filters = {}, employee_id) {
|
|
170
|
+
const policy = payrollPolicies[resource];
|
|
171
|
+
const query = {};
|
|
172
|
+
for (const key of policy.filters) {
|
|
173
|
+
// Authenticated employee scope takes precedence over selectable filters.
|
|
174
|
+
const value = key === "employee_id" && employee_id !== undefined
|
|
175
|
+
? employee_id
|
|
176
|
+
: filters[key];
|
|
177
|
+
if (value !== undefined)
|
|
178
|
+
Object.assign(query, queryParam(key, value));
|
|
179
|
+
}
|
|
180
|
+
return query;
|
|
168
181
|
}
|
|
169
182
|
export class PayrollsWorkspace {
|
|
170
183
|
payrolls;
|
|
@@ -234,9 +247,9 @@ export class PayrollsWorkspace {
|
|
|
234
247
|
if (!payrollCanRead(opts.context, opts.resource))
|
|
235
248
|
return emptySearchPage(opts.page, opts.per_page);
|
|
236
249
|
const owner_ids = employmentCatalogOwnerIDs(opts.context, opts.employer_ids);
|
|
237
|
-
const query = payrollFilterQuery(opts.resource, opts.filters
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
const query = payrollFilterQuery(opts.resource, opts.filters, opts.context.active_mode === UserTypeEmployee
|
|
251
|
+
? opts.context.owner_id
|
|
252
|
+
: undefined);
|
|
240
253
|
const port = this.ports[opts.resource];
|
|
241
254
|
if (payrollPolicies[opts.resource].searchable) {
|
|
242
255
|
return runOwnerScopeSearch({
|
|
@@ -483,6 +496,19 @@ export class PayrollsWorkspace {
|
|
|
483
496
|
break;
|
|
484
497
|
}
|
|
485
498
|
}
|
|
499
|
+
async updateFolder(actor, id, input) {
|
|
500
|
+
await this.owned(actor, PayrollResource.Folders, id);
|
|
501
|
+
const folder_name = input.folder_name.trim();
|
|
502
|
+
requirePayroll(folder_name, "invalid");
|
|
503
|
+
await this.payrolls.replaceOneAdjustmentFolder({
|
|
504
|
+
id,
|
|
505
|
+
in: {
|
|
506
|
+
folder_name,
|
|
507
|
+
folder_description: input.folder_description.trim(),
|
|
508
|
+
},
|
|
509
|
+
});
|
|
510
|
+
return this.owned(actor, PayrollResource.Folders, id);
|
|
511
|
+
}
|
|
486
512
|
async setArchived(actor, resource, record, value) {
|
|
487
513
|
requirePayroll(payrollCanManage(actor, record) && payrollPolicies[resource].archive, "access");
|
|
488
514
|
await this.owned(actor, resource, record.id);
|
|
@@ -491,9 +517,6 @@ export class PayrollsWorkspace {
|
|
|
491
517
|
case PayrollResource.Adjustments:
|
|
492
518
|
await this.payrolls.replaceOneAdjustment(opts);
|
|
493
519
|
break;
|
|
494
|
-
case PayrollResource.Folders:
|
|
495
|
-
await this.payrolls.replaceOneAdjustmentFolder(opts);
|
|
496
|
-
break;
|
|
497
520
|
case PayrollResource.PayConfigs:
|
|
498
521
|
await this.payrolls.replaceOnePayConfig(opts);
|
|
499
522
|
break;
|
|
@@ -518,5 +541,7 @@ export class PayrollsWorkspace {
|
|
|
518
541
|
await this.payrolls.deleteOnePayroll({ id: record.id });
|
|
519
542
|
else if (resource === PayrollResource.Programs)
|
|
520
543
|
await this.payrolls.deleteOnePayrollProgram({ id: record.id });
|
|
544
|
+
else if (resource === PayrollResource.Folders)
|
|
545
|
+
await this.payrolls.deleteOneAdjustmentFolder({ id: record.id });
|
|
521
546
|
}
|
|
522
547
|
}
|