@rachelallyson/planning-center-people-ts 2.14.1 → 3.1.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/CHANGELOG.md +82 -7
- package/README.md +42 -4
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +14 -6
- package/dist/client.d.ts +33 -8
- package/dist/client.js +47 -22
- package/dist/core.d.ts +4 -2
- package/dist/core.js +3 -2
- package/dist/error-handling.d.ts +4 -4
- package/dist/error-handling.js +13 -2
- package/dist/error-scenarios.d.ts +11 -7
- package/dist/error-scenarios.js +26 -10
- package/dist/helpers.d.ts +124 -48
- package/dist/helpers.js +237 -93
- package/dist/index.d.ts +10 -8
- package/dist/index.js +31 -72
- package/dist/matching/matcher.d.ts +8 -4
- package/dist/matching/matcher.js +51 -58
- package/dist/matching/scoring.d.ts +9 -6
- package/dist/matching/scoring.js +18 -14
- package/dist/modules/campus.d.ts +31 -36
- package/dist/modules/campus.js +36 -49
- package/dist/modules/contacts.d.ts +33 -29
- package/dist/modules/contacts.js +36 -12
- package/dist/modules/fields.d.ts +39 -55
- package/dist/modules/fields.js +65 -105
- package/dist/modules/forms.d.ts +35 -24
- package/dist/modules/forms.js +41 -23
- package/dist/modules/households.d.ts +17 -19
- package/dist/modules/households.js +25 -34
- package/dist/modules/lists.d.ts +38 -28
- package/dist/modules/lists.js +62 -42
- package/dist/modules/notes.d.ts +32 -30
- package/dist/modules/notes.js +40 -52
- package/dist/modules/people.d.ts +83 -71
- package/dist/modules/people.js +323 -172
- package/dist/modules/reports.d.ts +18 -32
- package/dist/modules/reports.js +28 -40
- package/dist/modules/service-time.d.ts +19 -24
- package/dist/modules/service-time.js +28 -28
- package/dist/modules/workflows.d.ts +42 -47
- package/dist/modules/workflows.js +52 -53
- package/dist/performance.d.ts +14 -10
- package/dist/performance.js +61 -25
- package/dist/testing/recorder.js +11 -2
- package/dist/testing/simple-builders.d.ts +6 -4
- package/dist/testing/simple-builders.js +36 -49
- package/dist/testing/types.d.ts +4 -0
- package/dist/types/api-options.d.ts +380 -0
- package/dist/types/api-options.js +6 -0
- package/dist/types/client.d.ts +4 -2
- package/dist/types/client.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/people.d.ts +61 -9
- package/package.json +7 -7
- package/dist/core/http.d.ts +0 -56
- package/dist/core/http.js +0 -360
- package/dist/core/pagination.d.ts +0 -34
- package/dist/core/pagination.js +0 -178
- package/dist/people/contacts.d.ts +0 -43
- package/dist/people/contacts.js +0 -122
- package/dist/people/core.d.ts +0 -28
- package/dist/people/core.js +0 -69
- package/dist/people/fields.d.ts +0 -68
- package/dist/people/fields.js +0 -305
- package/dist/people/households.d.ts +0 -15
- package/dist/people/households.js +0 -31
- package/dist/people/index.d.ts +0 -8
- package/dist/people/index.js +0 -25
- package/dist/people/lists.d.ts +0 -34
- package/dist/people/lists.js +0 -48
- package/dist/people/notes.d.ts +0 -30
- package/dist/people/notes.js +0 -37
- package/dist/people/organization.d.ts +0 -12
- package/dist/people/organization.js +0 -15
- package/dist/people/workflows.d.ts +0 -37
- package/dist/people/workflows.js +0 -75
package/dist/modules/people.js
CHANGED
|
@@ -25,55 +25,43 @@ exports.DEFAULT_AGGRESSIVE_RETRY_CONFIG = {
|
|
|
25
25
|
backoffMultiplier: 2,
|
|
26
26
|
};
|
|
27
27
|
class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
28
|
-
constructor(httpClient, paginationHelper, eventEmitter) {
|
|
29
|
-
super(httpClient, paginationHelper, eventEmitter);
|
|
30
|
-
this.personMatcher = new matcher_1.PersonMatcher(this);
|
|
28
|
+
constructor(httpClient, paginationHelper, eventEmitter, getConfig) {
|
|
29
|
+
super(httpClient, paginationHelper, eventEmitter, getConfig);
|
|
30
|
+
this.personMatcher = new matcher_1.PersonMatcher(this, getConfig);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Get all people with optional filtering
|
|
33
|
+
* Get all people across all pages with optional filtering
|
|
34
34
|
*/
|
|
35
35
|
async getAll(options = {}) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
if (options.include) {
|
|
43
|
-
params.include = options.include.join(',');
|
|
44
|
-
}
|
|
45
|
-
if (options.perPage) {
|
|
46
|
-
params.per_page = options.perPage;
|
|
47
|
-
}
|
|
48
|
-
if (options.page) {
|
|
49
|
-
params.page = options.page;
|
|
50
|
-
}
|
|
51
|
-
return this.getList('/people', params);
|
|
36
|
+
this.debugLog('people.getAll', { options });
|
|
37
|
+
return await this.getAllPages('/people', {
|
|
38
|
+
where: options.where,
|
|
39
|
+
include: options.include,
|
|
40
|
+
order: options.order
|
|
41
|
+
});
|
|
52
42
|
}
|
|
53
43
|
/**
|
|
54
|
-
* Get
|
|
44
|
+
* Get a single page of people with optional filtering and pagination control
|
|
45
|
+
* Use this when you need a specific page or want to limit the number of results
|
|
46
|
+
* @param options - List options including where, include, perPage, page, and order
|
|
47
|
+
* @returns A single page of results with meta and links for pagination
|
|
55
48
|
*/
|
|
56
|
-
async
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
return this.getAllPages('/people', params, paginationOptions);
|
|
49
|
+
async getPage(options = {}) {
|
|
50
|
+
this.debugLog('people.getPage', { options });
|
|
51
|
+
return this.getList('/people', {
|
|
52
|
+
where: options.where,
|
|
53
|
+
include: options.include,
|
|
54
|
+
per_page: options.perPage,
|
|
55
|
+
page: options.page,
|
|
56
|
+
order: options.order
|
|
57
|
+
});
|
|
67
58
|
}
|
|
68
59
|
/**
|
|
69
60
|
* Get a single person by ID
|
|
70
61
|
*/
|
|
71
62
|
async getById(id, include) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
params.include = include.join(',');
|
|
75
|
-
}
|
|
76
|
-
return this.getSingle(`/people/${id}`, params);
|
|
63
|
+
this.debugLog('people.getById', { id, include });
|
|
64
|
+
return this.getSingle(`/people/${id}`, include);
|
|
77
65
|
}
|
|
78
66
|
/**
|
|
79
67
|
* Verify that a person exists in PCO
|
|
@@ -87,7 +75,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
87
75
|
* @returns True if person exists, false if not found
|
|
88
76
|
* @throws Error if request times out or other error occurs (except 404)
|
|
89
77
|
*
|
|
90
|
-
* @
|
|
78
|
+
* @gmail.com
|
|
91
79
|
* ```typescript
|
|
92
80
|
* const exists = await client.people.verifyPersonExists(cachedPersonId);
|
|
93
81
|
* if (!exists) {
|
|
@@ -97,12 +85,15 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
97
85
|
* ```
|
|
98
86
|
*/
|
|
99
87
|
async verifyPersonExists(personId, options) {
|
|
88
|
+
this.debugLog('people.verifyPersonExists', { personId, options });
|
|
100
89
|
const timeout = options?.timeout ?? 30000;
|
|
101
90
|
const verificationPromise = this.getById(personId)
|
|
102
91
|
.then(() => true)
|
|
103
92
|
.catch((error) => {
|
|
104
93
|
// 404 means person doesn't exist (merged or deleted)
|
|
105
|
-
|
|
94
|
+
const status = error?.status
|
|
95
|
+
?? error?.response?.status;
|
|
96
|
+
if (status === 404) {
|
|
106
97
|
return false;
|
|
107
98
|
}
|
|
108
99
|
// Re-throw other errors
|
|
@@ -115,22 +106,167 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
115
106
|
});
|
|
116
107
|
return Promise.race([verificationPromise, timeoutPromise]);
|
|
117
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Transform PersonCreateOptions (camelCase) to API format (snake_case)
|
|
111
|
+
* Also handles snake_case input directly (passes through)
|
|
112
|
+
*/
|
|
113
|
+
transformPersonData(data) {
|
|
114
|
+
const transformed = {};
|
|
115
|
+
const dataObj = data;
|
|
116
|
+
// If data is already in snake_case format, copy those fields directly
|
|
117
|
+
if (dataObj.first_name !== undefined)
|
|
118
|
+
transformed.first_name = dataObj.first_name;
|
|
119
|
+
if (dataObj.last_name !== undefined)
|
|
120
|
+
transformed.last_name = dataObj.last_name;
|
|
121
|
+
if (dataObj.given_name !== undefined)
|
|
122
|
+
transformed.given_name = dataObj.given_name;
|
|
123
|
+
if (dataObj.middle_name !== undefined)
|
|
124
|
+
transformed.middle_name = dataObj.middle_name;
|
|
125
|
+
if (dataObj.nickname !== undefined)
|
|
126
|
+
transformed.nickname = dataObj.nickname;
|
|
127
|
+
if (dataObj.birthdate !== undefined)
|
|
128
|
+
transformed.birthdate = dataObj.birthdate;
|
|
129
|
+
if (dataObj.anniversary !== undefined)
|
|
130
|
+
transformed.anniversary = dataObj.anniversary;
|
|
131
|
+
if (dataObj.gender !== undefined)
|
|
132
|
+
transformed.gender = dataObj.gender;
|
|
133
|
+
if (dataObj.grade !== undefined)
|
|
134
|
+
transformed.grade = dataObj.grade;
|
|
135
|
+
if (dataObj.child !== undefined)
|
|
136
|
+
transformed.child = dataObj.child;
|
|
137
|
+
if (dataObj.status !== undefined)
|
|
138
|
+
transformed.status = dataObj.status;
|
|
139
|
+
if (dataObj.medical_notes !== undefined)
|
|
140
|
+
transformed.medical_notes = dataObj.medical_notes;
|
|
141
|
+
if (dataObj.job_title !== undefined)
|
|
142
|
+
transformed.job_title = dataObj.job_title;
|
|
143
|
+
if (dataObj.employer !== undefined)
|
|
144
|
+
transformed.employer = dataObj.employer;
|
|
145
|
+
if (dataObj.school !== undefined)
|
|
146
|
+
transformed.school = dataObj.school;
|
|
147
|
+
if (dataObj.graduation_year !== undefined)
|
|
148
|
+
transformed.graduation_year = dataObj.graduation_year;
|
|
149
|
+
if (dataObj.avatar !== undefined)
|
|
150
|
+
transformed.avatar = dataObj.avatar;
|
|
151
|
+
if (dataObj.site_administrator !== undefined)
|
|
152
|
+
transformed.site_administrator = dataObj.site_administrator;
|
|
153
|
+
if (dataObj.accounting_administrator !== undefined)
|
|
154
|
+
transformed.accounting_administrator = dataObj.accounting_administrator;
|
|
155
|
+
if (dataObj.people_permissions !== undefined)
|
|
156
|
+
transformed.people_permissions = dataObj.people_permissions;
|
|
157
|
+
if (dataObj.directory_status !== undefined)
|
|
158
|
+
transformed.directory_status = dataObj.directory_status;
|
|
159
|
+
if (dataObj.login_identifier !== undefined)
|
|
160
|
+
transformed.login_identifier = dataObj.login_identifier;
|
|
161
|
+
if (dataObj.membership !== undefined)
|
|
162
|
+
transformed.membership = dataObj.membership;
|
|
163
|
+
if (dataObj.remote_id !== undefined)
|
|
164
|
+
transformed.remote_id = dataObj.remote_id;
|
|
165
|
+
if (dataObj.demographic_avatar_url !== undefined)
|
|
166
|
+
transformed.demographic_avatar_url = dataObj.demographic_avatar_url;
|
|
167
|
+
if (dataObj.inactivated_at !== undefined)
|
|
168
|
+
transformed.inactivated_at = dataObj.inactivated_at;
|
|
169
|
+
if (dataObj.resource_permission_flags !== undefined)
|
|
170
|
+
transformed.resource_permission_flags = dataObj.resource_permission_flags;
|
|
171
|
+
if (dataObj.primary_campus_id !== undefined)
|
|
172
|
+
transformed.primary_campus_id = dataObj.primary_campus_id;
|
|
173
|
+
if (dataObj.household_id !== undefined)
|
|
174
|
+
transformed.household_id = dataObj.household_id;
|
|
175
|
+
// Handle PersonCreateOptions fields (camelCase)
|
|
176
|
+
if (dataObj.firstName !== undefined)
|
|
177
|
+
transformed.first_name = dataObj.firstName;
|
|
178
|
+
if (dataObj.lastName !== undefined)
|
|
179
|
+
transformed.last_name = dataObj.lastName;
|
|
180
|
+
if (dataObj.givenName !== undefined)
|
|
181
|
+
transformed.given_name = dataObj.givenName;
|
|
182
|
+
if (dataObj.middleName !== undefined)
|
|
183
|
+
transformed.middle_name = dataObj.middleName;
|
|
184
|
+
if (dataObj.nickname !== undefined)
|
|
185
|
+
transformed.nickname = dataObj.nickname;
|
|
186
|
+
if (dataObj.birthdate !== undefined)
|
|
187
|
+
transformed.birthdate = dataObj.birthdate;
|
|
188
|
+
if (dataObj.anniversary !== undefined)
|
|
189
|
+
transformed.anniversary = dataObj.anniversary;
|
|
190
|
+
if (dataObj.gender !== undefined)
|
|
191
|
+
transformed.gender = dataObj.gender;
|
|
192
|
+
if (dataObj.grade !== undefined)
|
|
193
|
+
transformed.grade = dataObj.grade;
|
|
194
|
+
if (dataObj.child !== undefined)
|
|
195
|
+
transformed.child = dataObj.child;
|
|
196
|
+
if (dataObj.status !== undefined)
|
|
197
|
+
transformed.status = dataObj.status;
|
|
198
|
+
if (dataObj.medicalNotes !== undefined)
|
|
199
|
+
transformed.medical_notes = dataObj.medicalNotes;
|
|
200
|
+
if (dataObj.jobTitle !== undefined)
|
|
201
|
+
transformed.job_title = dataObj.jobTitle;
|
|
202
|
+
if (dataObj.employer !== undefined)
|
|
203
|
+
transformed.employer = dataObj.employer;
|
|
204
|
+
if (dataObj.school !== undefined)
|
|
205
|
+
transformed.school = dataObj.school;
|
|
206
|
+
if (dataObj.graduationYear !== undefined)
|
|
207
|
+
transformed.graduation_year = dataObj.graduationYear;
|
|
208
|
+
if (dataObj.avatar !== undefined)
|
|
209
|
+
transformed.avatar = dataObj.avatar;
|
|
210
|
+
if (dataObj.siteAdministrator !== undefined)
|
|
211
|
+
transformed.site_administrator = dataObj.siteAdministrator;
|
|
212
|
+
if (dataObj.accountingAdministrator !== undefined)
|
|
213
|
+
transformed.accounting_administrator = dataObj.accountingAdministrator;
|
|
214
|
+
if (dataObj.peoplePermissions !== undefined)
|
|
215
|
+
transformed.people_permissions = dataObj.peoplePermissions;
|
|
216
|
+
if (dataObj.directoryStatus !== undefined)
|
|
217
|
+
transformed.directory_status = dataObj.directoryStatus;
|
|
218
|
+
if (dataObj.loginIdentifier !== undefined)
|
|
219
|
+
transformed.login_identifier = dataObj.loginIdentifier;
|
|
220
|
+
if (dataObj.membership !== undefined)
|
|
221
|
+
transformed.membership = dataObj.membership;
|
|
222
|
+
if (dataObj.remoteId !== undefined)
|
|
223
|
+
transformed.remote_id = dataObj.remoteId;
|
|
224
|
+
if (dataObj.demographicAvatarUrl !== undefined)
|
|
225
|
+
transformed.demographic_avatar_url = dataObj.demographicAvatarUrl;
|
|
226
|
+
if (dataObj.inactivatedAt !== undefined)
|
|
227
|
+
transformed.inactivated_at = dataObj.inactivatedAt;
|
|
228
|
+
if (dataObj.resourcePermissionFlags !== undefined)
|
|
229
|
+
transformed.resource_permission_flags = dataObj.resourcePermissionFlags;
|
|
230
|
+
// Handle relationship fields
|
|
231
|
+
if (dataObj.primaryCampusId !== undefined)
|
|
232
|
+
transformed.primary_campus_id = dataObj.primaryCampusId;
|
|
233
|
+
if (dataObj.householdId !== undefined)
|
|
234
|
+
transformed.household_id = dataObj.householdId;
|
|
235
|
+
return transformed;
|
|
236
|
+
}
|
|
118
237
|
/**
|
|
119
238
|
* Create a new person
|
|
239
|
+
* Accepts both camelCase (PersonCreateOptions) and snake_case (PersonAttributes) fields
|
|
120
240
|
*/
|
|
121
241
|
async create(data) {
|
|
122
|
-
|
|
242
|
+
this.debugLog('people.create', { data });
|
|
243
|
+
// Check if data is already in snake_case format (has first_name, last_name, etc.)
|
|
244
|
+
const hasSnakeCase = Object.keys(data).some(key => key.includes('_'));
|
|
245
|
+
// If it's already in snake_case, use it directly; otherwise transform
|
|
246
|
+
const transformedData = hasSnakeCase
|
|
247
|
+
? data
|
|
248
|
+
: this.transformPersonData(data);
|
|
249
|
+
return this.createResource('/people', transformedData);
|
|
123
250
|
}
|
|
124
251
|
/**
|
|
125
252
|
* Update a person
|
|
253
|
+
* Accepts both camelCase (PersonCreateOptions) and snake_case (PersonAttributes) fields
|
|
126
254
|
*/
|
|
127
255
|
async update(id, data) {
|
|
128
|
-
|
|
256
|
+
this.debugLog('people.update', { id, data });
|
|
257
|
+
// Check if data is already in snake_case format (has first_name, last_name, etc.)
|
|
258
|
+
const hasSnakeCase = Object.keys(data).some(key => key.includes('_'));
|
|
259
|
+
// If it's already in snake_case, use it directly; otherwise transform
|
|
260
|
+
const transformedData = hasSnakeCase
|
|
261
|
+
? data
|
|
262
|
+
: this.transformPersonData(data);
|
|
263
|
+
return this.updateResource(`/people/${id}`, transformedData);
|
|
129
264
|
}
|
|
130
265
|
/**
|
|
131
266
|
* Delete a person
|
|
132
267
|
*/
|
|
133
268
|
async delete(id) {
|
|
269
|
+
this.debugLog('people.delete', { id });
|
|
134
270
|
return this.deleteResource(`/people/${id}`);
|
|
135
271
|
}
|
|
136
272
|
// ===== Relationship Management =====
|
|
@@ -138,203 +274,193 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
138
274
|
* Get a person's primary campus
|
|
139
275
|
*/
|
|
140
276
|
async getPrimaryCampus(personId) {
|
|
277
|
+
this.debugLog('people.getPrimaryCampus', { personId });
|
|
141
278
|
const person = await this.getById(personId, ['primary_campus']);
|
|
142
|
-
const campusData = person.
|
|
143
|
-
|
|
279
|
+
const campusData = person.primary_campus;
|
|
280
|
+
// campusData can be CampusResource, ResourceIdentifier, or null
|
|
281
|
+
if (!campusData || Array.isArray(campusData)) {
|
|
144
282
|
return null;
|
|
145
283
|
}
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
284
|
+
// Check if it's a ResourceIdentifier (has id but might not have full attributes)
|
|
285
|
+
if ('id' in campusData && 'type' in campusData) {
|
|
286
|
+
// Get the full campus resource
|
|
287
|
+
return this.getSingle(`/campuses/${campusData.id}`);
|
|
288
|
+
}
|
|
289
|
+
// If it's already a full resource, return it
|
|
290
|
+
return campusData;
|
|
151
291
|
}
|
|
152
292
|
/**
|
|
153
293
|
* Set a person's primary campus
|
|
154
294
|
*/
|
|
155
295
|
async setPrimaryCampus(personId, campusId) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
data: {
|
|
160
|
-
data: {
|
|
161
|
-
type: 'Person',
|
|
162
|
-
id: personId,
|
|
163
|
-
attributes: {
|
|
164
|
-
primary_campus_id: campusId
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}).then(response => response.data.data);
|
|
296
|
+
this.debugLog('people.setPrimaryCampus', { personId, campusId });
|
|
297
|
+
const transformedData = this.transformPersonData({ primaryCampusId: campusId });
|
|
298
|
+
return this.updateResource(`/people/${personId}`, transformedData);
|
|
169
299
|
}
|
|
170
300
|
/**
|
|
171
301
|
* Remove a person's primary campus
|
|
172
302
|
*/
|
|
173
303
|
async removePrimaryCampus(personId) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
data: {
|
|
178
|
-
data: {
|
|
179
|
-
type: 'Person',
|
|
180
|
-
id: personId,
|
|
181
|
-
attributes: {
|
|
182
|
-
primary_campus_id: null
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}).then(response => response.data.data);
|
|
304
|
+
this.debugLog('people.removePrimaryCampus', { personId });
|
|
305
|
+
const transformedData = this.transformPersonData({ primaryCampusId: null });
|
|
306
|
+
return this.updateResource(`/people/${personId}`, transformedData);
|
|
187
307
|
}
|
|
188
308
|
/**
|
|
189
309
|
* Get a person's household
|
|
190
310
|
*/
|
|
191
311
|
async getHousehold(personId) {
|
|
312
|
+
this.debugLog('people.getHousehold', { personId });
|
|
192
313
|
const person = await this.getById(personId, ['household']);
|
|
193
|
-
const householdData = person.
|
|
194
|
-
|
|
314
|
+
const householdData = person.household;
|
|
315
|
+
// householdData can be HouseholdResource, ResourceIdentifier, or null
|
|
316
|
+
if (!householdData || Array.isArray(householdData)) {
|
|
195
317
|
return null;
|
|
196
318
|
}
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
319
|
+
// Check if it's a ResourceIdentifier (has id but might not have full attributes)
|
|
320
|
+
if ('id' in householdData && 'type' in householdData) {
|
|
321
|
+
// Get the full household resource
|
|
322
|
+
return this.getSingle(`/households/${householdData.id}`);
|
|
323
|
+
}
|
|
324
|
+
// If it's already a full resource, return it
|
|
325
|
+
return householdData;
|
|
202
326
|
}
|
|
203
327
|
/**
|
|
204
328
|
* Set a person's household
|
|
329
|
+
* Uses the household_memberships endpoint to create a membership record
|
|
205
330
|
*/
|
|
206
331
|
async setHousehold(personId, householdId) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
attributes: {
|
|
215
|
-
household_id: householdId
|
|
332
|
+
this.debugLog('people.setHousehold', { personId, householdId });
|
|
333
|
+
await this.createResource(`/households/${householdId}/household_memberships`, {
|
|
334
|
+
relationships: {
|
|
335
|
+
person: {
|
|
336
|
+
data: {
|
|
337
|
+
type: 'Person',
|
|
338
|
+
id: personId
|
|
216
339
|
}
|
|
217
340
|
}
|
|
218
341
|
}
|
|
219
|
-
})
|
|
342
|
+
});
|
|
343
|
+
// Return the updated person
|
|
344
|
+
return this.getById(personId);
|
|
220
345
|
}
|
|
221
346
|
/**
|
|
222
347
|
* Remove a person from their household
|
|
348
|
+
* Uses the household_memberships endpoint to delete the membership record
|
|
223
349
|
*/
|
|
224
350
|
async removeFromHousehold(personId) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
351
|
+
this.debugLog('people.removeFromHousehold', { personId });
|
|
352
|
+
const membershipsResponse = await this.httpClient.request({
|
|
353
|
+
method: 'GET',
|
|
354
|
+
endpoint: `/people/${personId}/household_memberships`
|
|
355
|
+
});
|
|
356
|
+
if (!membershipsResponse.data.data || membershipsResponse.data.data.length === 0) {
|
|
357
|
+
throw new Error(`Person ${personId} is not in a household`);
|
|
358
|
+
}
|
|
359
|
+
// Get the first membership (a person can only be in one household)
|
|
360
|
+
const membership = membershipsResponse.data.data[0];
|
|
361
|
+
const membershipId = membership.id;
|
|
362
|
+
// Get the household ID from the membership relationship
|
|
363
|
+
const membershipHousehold = membership.relationships?.household?.data;
|
|
364
|
+
if (!membershipHousehold || Array.isArray(membershipHousehold) || !membershipHousehold.id) {
|
|
365
|
+
const membershipDetails = await this.httpClient.request({
|
|
366
|
+
method: 'GET',
|
|
367
|
+
endpoint: `/people/${personId}/household_memberships/${membershipId}`,
|
|
368
|
+
params: {
|
|
369
|
+
include: 'household'
|
|
235
370
|
}
|
|
371
|
+
});
|
|
372
|
+
const householdData = membershipDetails.data.data.relationships?.household?.data;
|
|
373
|
+
if (!householdData || Array.isArray(householdData) || !householdData.id) {
|
|
374
|
+
throw new Error(`Could not determine household ID for membership ${membershipId}`);
|
|
236
375
|
}
|
|
237
|
-
|
|
376
|
+
const householdId = householdData.id;
|
|
377
|
+
await this.deleteResource(`/households/${householdId}/household_memberships/${membershipId}`);
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
const householdId = membershipHousehold.id;
|
|
381
|
+
await this.deleteResource(`/households/${householdId}/household_memberships/${membershipId}`);
|
|
382
|
+
}
|
|
383
|
+
// Return the updated person
|
|
384
|
+
return this.getById(personId);
|
|
238
385
|
}
|
|
239
386
|
/**
|
|
240
387
|
* Get all people in a specific household
|
|
388
|
+
* Note: This uses getList() internally, so it returns a single page. Use getAll() with where[household_id] for all pages.
|
|
241
389
|
*/
|
|
242
390
|
async getHouseholdMembers(householdId, options = {}) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
391
|
+
this.debugLog('people.getHouseholdMembers', { householdId, options });
|
|
392
|
+
// household_id is not in PersonWhereClause, so we need to use flat params
|
|
393
|
+
// Build the where clause manually and merge with other options
|
|
394
|
+
const params = {};
|
|
395
|
+
if (options.include)
|
|
247
396
|
params.include = options.include.join(',');
|
|
248
|
-
|
|
249
|
-
if (options.perPage) {
|
|
397
|
+
if (options.perPage)
|
|
250
398
|
params.per_page = options.perPage;
|
|
251
|
-
|
|
252
|
-
if (options.page) {
|
|
399
|
+
if (options.page)
|
|
253
400
|
params.page = options.page;
|
|
254
|
-
|
|
401
|
+
params['where[household_id]'] = householdId;
|
|
255
402
|
return this.getList('/people', params);
|
|
256
403
|
}
|
|
257
404
|
/**
|
|
258
405
|
* Get people by campus
|
|
406
|
+
* Note: This uses getList() internally, so it returns a single page. Use getAll() with where[primary_campus_id] for all pages.
|
|
259
407
|
*/
|
|
260
408
|
async getByCampus(campusId, options = {}) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
return this.getList('/people', params);
|
|
409
|
+
this.debugLog('people.getByCampus', { campusId, options });
|
|
410
|
+
const campusIdNum = Number(campusId);
|
|
411
|
+
if (isNaN(campusIdNum)) {
|
|
412
|
+
throw new Error(`Invalid campus ID: ${campusId}`);
|
|
413
|
+
}
|
|
414
|
+
return this.getList('/people', {
|
|
415
|
+
where: { primary_campus_id: campusIdNum },
|
|
416
|
+
include: options.include,
|
|
417
|
+
per_page: options.perPage,
|
|
418
|
+
page: options.page
|
|
419
|
+
});
|
|
274
420
|
}
|
|
275
421
|
/**
|
|
276
422
|
* Get a person's workflow cards
|
|
277
423
|
*/
|
|
278
424
|
async getWorkflowCards(personId, options = {}) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
if (options.page) {
|
|
287
|
-
params.page = options.page;
|
|
288
|
-
}
|
|
289
|
-
return this.getList(`/people/${personId}/workflow_cards`, params);
|
|
425
|
+
this.debugLog('people.getWorkflowCards', { personId, options });
|
|
426
|
+
return this.getList(`/people/${personId}/workflow_cards`, {
|
|
427
|
+
include: options.include,
|
|
428
|
+
per_page: options.perPage,
|
|
429
|
+
page: options.page
|
|
430
|
+
});
|
|
290
431
|
}
|
|
291
432
|
/**
|
|
292
433
|
* Get a person's notes
|
|
293
434
|
*/
|
|
294
435
|
async getNotes(personId, options = {}) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
if (options.page) {
|
|
303
|
-
params.page = options.page;
|
|
304
|
-
}
|
|
305
|
-
return this.getList(`/people/${personId}/notes`, params);
|
|
436
|
+
this.debugLog('people.getNotes', { personId, options });
|
|
437
|
+
return this.getList(`/people/${personId}/notes`, {
|
|
438
|
+
include: options.include,
|
|
439
|
+
per_page: options.perPage,
|
|
440
|
+
page: options.page
|
|
441
|
+
});
|
|
306
442
|
}
|
|
307
443
|
/**
|
|
308
444
|
* Get a person's field data
|
|
309
445
|
*/
|
|
310
446
|
async getFieldData(personId, options = {}) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
if (options.page) {
|
|
319
|
-
params.page = options.page;
|
|
320
|
-
}
|
|
321
|
-
return this.getList(`/people/${personId}/field_data`, params);
|
|
447
|
+
this.debugLog('people.getFieldData', { personId, options });
|
|
448
|
+
return this.getList(`/people/${personId}/field_data`, {
|
|
449
|
+
include: options.include,
|
|
450
|
+
per_page: options.perPage,
|
|
451
|
+
page: options.page
|
|
452
|
+
});
|
|
322
453
|
}
|
|
323
454
|
/**
|
|
324
455
|
* Get a person's social profiles
|
|
325
456
|
*/
|
|
326
457
|
async getSocialProfiles(personId, options = {}) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
if (options.page) {
|
|
335
|
-
params.page = options.page;
|
|
336
|
-
}
|
|
337
|
-
return this.getList(`/people/${personId}/social_profiles`, params);
|
|
458
|
+
this.debugLog('people.getSocialProfiles', { personId, options });
|
|
459
|
+
return this.getList(`/people/${personId}/social_profiles`, {
|
|
460
|
+
include: options.include,
|
|
461
|
+
per_page: options.perPage,
|
|
462
|
+
page: options.page
|
|
463
|
+
});
|
|
338
464
|
}
|
|
339
465
|
/**
|
|
340
466
|
* Find or create a person with smart matching
|
|
@@ -347,13 +473,13 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
347
473
|
* to a person's profile when a match is found. The contacts are added as non-primary
|
|
348
474
|
* to preserve existing primary contacts.
|
|
349
475
|
*
|
|
350
|
-
* @
|
|
476
|
+
* @gmail.com
|
|
351
477
|
* ```typescript
|
|
352
478
|
* // Basic find or create
|
|
353
479
|
* const person = await client.people.findOrCreate({
|
|
354
480
|
* firstName: 'John',
|
|
355
481
|
* lastName: 'Doe',
|
|
356
|
-
* email: 'john@
|
|
482
|
+
* email: 'john@gmail.com',
|
|
357
483
|
* phone: '+1234567890'
|
|
358
484
|
* });
|
|
359
485
|
*
|
|
@@ -361,7 +487,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
361
487
|
* const person = await client.people.findOrCreate({
|
|
362
488
|
* firstName: 'Jane',
|
|
363
489
|
* lastName: 'Smith',
|
|
364
|
-
* email: 'jane@
|
|
490
|
+
* email: 'jane@gmail.com',
|
|
365
491
|
* phone: '+1987654321',
|
|
366
492
|
* addMissingContactInfo: true // Will add phone if person only has email
|
|
367
493
|
* });
|
|
@@ -370,12 +496,14 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
370
496
|
* @returns The found or newly created person
|
|
371
497
|
*/
|
|
372
498
|
async findOrCreate(options) {
|
|
499
|
+
this.debugLog('people.findOrCreate', { options });
|
|
373
500
|
return this.personMatcher.findOrCreate(options);
|
|
374
501
|
}
|
|
375
502
|
/**
|
|
376
503
|
* Search people by multiple criteria
|
|
377
504
|
*/
|
|
378
505
|
async search(criteria) {
|
|
506
|
+
this.debugLog('people.search', { criteria });
|
|
379
507
|
const where = {};
|
|
380
508
|
// Use flexible search when we have multiple criteria or want broader matching
|
|
381
509
|
if (criteria.email || criteria.phone) {
|
|
@@ -394,9 +522,16 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
394
522
|
if (criteria.status) {
|
|
395
523
|
where.status = criteria.status;
|
|
396
524
|
}
|
|
525
|
+
// If pagination options are provided, use getPage instead of getAll
|
|
526
|
+
if (criteria.perPage !== undefined || criteria.page !== undefined) {
|
|
527
|
+
return this.getPage({
|
|
528
|
+
where,
|
|
529
|
+
perPage: criteria.perPage,
|
|
530
|
+
page: criteria.page,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
397
533
|
return this.getAll({
|
|
398
534
|
where,
|
|
399
|
-
perPage: criteria.perPage || 25,
|
|
400
535
|
});
|
|
401
536
|
}
|
|
402
537
|
// Contact methods
|
|
@@ -404,96 +539,112 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
404
539
|
* Get person's emails
|
|
405
540
|
*/
|
|
406
541
|
async getEmails(personId) {
|
|
542
|
+
this.debugLog('people.getEmails', { personId });
|
|
407
543
|
return this.getList(`/people/${personId}/emails`);
|
|
408
544
|
}
|
|
409
545
|
/**
|
|
410
546
|
* Add an email to a person
|
|
411
547
|
*/
|
|
412
548
|
async addEmail(personId, data) {
|
|
549
|
+
this.debugLog('people.addEmail', { personId, data });
|
|
413
550
|
return this.createResource(`/people/${personId}/emails`, data);
|
|
414
551
|
}
|
|
415
552
|
/**
|
|
416
553
|
* Update a person's email
|
|
417
554
|
*/
|
|
418
555
|
async updateEmail(personId, emailId, data) {
|
|
556
|
+
this.debugLog('people.updateEmail', { personId, emailId, data });
|
|
419
557
|
return this.updateResource(`/people/${personId}/emails/${emailId}`, data);
|
|
420
558
|
}
|
|
421
559
|
/**
|
|
422
560
|
* Delete a person's email
|
|
423
561
|
*/
|
|
424
562
|
async deleteEmail(personId, emailId) {
|
|
563
|
+
this.debugLog('people.deleteEmail', { personId, emailId });
|
|
425
564
|
return this.deleteResource(`/people/${personId}/emails/${emailId}`);
|
|
426
565
|
}
|
|
427
566
|
/**
|
|
428
567
|
* Get person's phone numbers
|
|
429
568
|
*/
|
|
430
569
|
async getPhoneNumbers(personId) {
|
|
570
|
+
this.debugLog('people.getPhoneNumbers', { personId });
|
|
431
571
|
return this.getList(`/people/${personId}/phone_numbers`);
|
|
432
572
|
}
|
|
433
573
|
/**
|
|
434
574
|
* Add a phone number to a person
|
|
435
575
|
*/
|
|
436
576
|
async addPhoneNumber(personId, data) {
|
|
577
|
+
this.debugLog('people.addPhoneNumber', { personId, data });
|
|
437
578
|
return this.createResource(`/people/${personId}/phone_numbers`, data);
|
|
438
579
|
}
|
|
439
580
|
/**
|
|
440
581
|
* Update a person's phone number
|
|
441
582
|
*/
|
|
442
583
|
async updatePhoneNumber(personId, phoneId, data) {
|
|
584
|
+
this.debugLog('people.updatePhoneNumber', { personId, phoneId, data });
|
|
443
585
|
return this.updateResource(`/people/${personId}/phone_numbers/${phoneId}`, data);
|
|
444
586
|
}
|
|
445
587
|
/**
|
|
446
588
|
* Delete a person's phone number
|
|
447
589
|
*/
|
|
448
590
|
async deletePhoneNumber(personId, phoneId) {
|
|
591
|
+
this.debugLog('people.deletePhoneNumber', { personId, phoneId });
|
|
449
592
|
return this.deleteResource(`/people/${personId}/phone_numbers/${phoneId}`);
|
|
450
593
|
}
|
|
451
594
|
/**
|
|
452
595
|
* Get person's addresses
|
|
453
596
|
*/
|
|
454
597
|
async getAddresses(personId) {
|
|
598
|
+
this.debugLog('people.getAddresses', { personId });
|
|
455
599
|
return this.getList(`/people/${personId}/addresses`);
|
|
456
600
|
}
|
|
457
601
|
/**
|
|
458
602
|
* Add an address to a person
|
|
459
603
|
*/
|
|
460
604
|
async addAddress(personId, data) {
|
|
605
|
+
this.debugLog('people.addAddress', { personId, data });
|
|
461
606
|
return this.createResource(`/people/${personId}/addresses`, data);
|
|
462
607
|
}
|
|
463
608
|
/**
|
|
464
609
|
* Update a person's address
|
|
465
610
|
*/
|
|
466
611
|
async updateAddress(personId, addressId, data) {
|
|
612
|
+
this.debugLog('people.updateAddress', { personId, addressId, data });
|
|
467
613
|
return this.updateResource(`/people/${personId}/addresses/${addressId}`, data);
|
|
468
614
|
}
|
|
469
615
|
/**
|
|
470
616
|
* Delete a person's address
|
|
471
617
|
*/
|
|
472
618
|
async deleteAddress(personId, addressId) {
|
|
619
|
+
this.debugLog('people.deleteAddress', { personId, addressId });
|
|
473
620
|
return this.deleteResource(`/people/${personId}/addresses/${addressId}`);
|
|
474
621
|
}
|
|
475
622
|
/**
|
|
476
623
|
* Add a social profile to a person
|
|
477
624
|
*/
|
|
478
625
|
async addSocialProfile(personId, data) {
|
|
626
|
+
this.debugLog('people.addSocialProfile', { personId, data });
|
|
479
627
|
return this.createResource(`/people/${personId}/social_profiles`, data);
|
|
480
628
|
}
|
|
481
629
|
/**
|
|
482
630
|
* Update a person's social profile
|
|
483
631
|
*/
|
|
484
632
|
async updateSocialProfile(personId, profileId, data) {
|
|
633
|
+
this.debugLog('people.updateSocialProfile', { personId, profileId, data });
|
|
485
634
|
return this.updateResource(`/people/${personId}/social_profiles/${profileId}`, data);
|
|
486
635
|
}
|
|
487
636
|
/**
|
|
488
637
|
* Delete a person's social profile
|
|
489
638
|
*/
|
|
490
639
|
async deleteSocialProfile(personId, profileId) {
|
|
640
|
+
this.debugLog('people.deleteSocialProfile', { personId, profileId });
|
|
491
641
|
return this.deleteResource(`/people/${personId}/social_profiles/${profileId}`);
|
|
492
642
|
}
|
|
493
643
|
/**
|
|
494
644
|
* Create a person with contact information
|
|
495
645
|
*/
|
|
496
646
|
async createWithContacts(personData, contacts) {
|
|
647
|
+
this.debugLog('people.createWithContacts', { personData, contacts });
|
|
497
648
|
const person = await this.create(personData);
|
|
498
649
|
const result = { person };
|
|
499
650
|
if (contacts?.email) {
|