1 | |
2 | type Paylocity = { |
3 | clientId: string |
4 | clientSecret: string |
5 | } |
6 | |
7 | * Add new employee to Web Link |
8 | * Add new employee to Web Link will send partially completed or potentially erroneous new hire record to Web Link, where it can be corrected and competed by company administrator or authorized Paylocity Service Bureau employee. |
9 | */ |
10 | export async function main( |
11 | auth: Paylocity, |
12 | companyId: string, |
13 | body: { |
14 | additionalDirectDeposit?: { |
15 | accountNumber?: string |
16 | accountType?: string |
17 | amount?: number |
18 | amountType?: string |
19 | isSkipPreNote?: false | true |
20 | preNoteDate?: string |
21 | routingNumber?: string |
22 | }[] |
23 | benefitSetup?: { |
24 | benefitClass?: string |
25 | benefitClassEffectiveDate?: string |
26 | benefitSalary?: number |
27 | benefitSalaryEffectiveDate?: string |
28 | doNotApplyAdministrativePeriod?: false | true |
29 | isMeasureAcaEligibility?: false | true |
30 | }[] |
31 | birthDate?: string |
32 | customBooleanFields?: { |
33 | category: 'PayrollAndHR' |
34 | label: string |
35 | value: false | true |
36 | }[] |
37 | customDateFields?: { |
38 | category: 'PayrollAndHR' |
39 | label: string |
40 | value: string |
41 | }[] |
42 | customDropDownFields?: { |
43 | category: 'PayrollAndHR' |
44 | label: string |
45 | value: string |
46 | }[] |
47 | customNumberFields?: { |
48 | category: 'PayrollAndHR' |
49 | label: string |
50 | value: number |
51 | }[] |
52 | customTextFields?: { |
53 | category: 'PayrollAndHR' |
54 | label: string |
55 | value: string |
56 | }[] |
57 | departmentPosition?: { |
58 | changeReason?: string |
59 | clockBadgeNumber?: string |
60 | costCenter1?: string |
61 | costCenter2?: string |
62 | costCenter3?: string |
63 | effectiveDate?: string |
64 | employeeType?: string |
65 | equalEmploymentOpportunityClass?: string |
66 | isMinimumWageExempt?: false | true |
67 | isOvertimeExempt?: false | true |
68 | isSupervisorReviewer?: false | true |
69 | isUnionDuesCollected?: false | true |
70 | isUnionInitiationCollected?: false | true |
71 | jobTitle?: string |
72 | payGroup?: string |
73 | positionCode?: string |
74 | shift?: string |
75 | supervisorCompanyNumber?: string |
76 | supervisorEmployeeId?: string |
77 | tipped?: string |
78 | unionAffiliationDate?: string |
79 | unionCode?: string |
80 | unionPosition?: string |
81 | workersCompensation?: string |
82 | }[] |
83 | disabilityDescription?: string |
84 | employeeId?: string |
85 | ethnicity?: string |
86 | federalTax?: { |
87 | amount?: number |
88 | deductionsAmount?: number |
89 | dependentsAmount?: number |
90 | exemptions?: number |
91 | filingStatus?: string |
92 | higherRate?: false | true |
93 | otherIncomeAmount?: number |
94 | percentage?: number |
95 | taxCalculationCode?: string |
96 | w4FormYear?: number |
97 | }[] |
98 | firstName?: string |
99 | fitwExemptReason?: string |
100 | futaExemptReason?: string |
101 | gender?: string |
102 | homeAddress?: { |
103 | address1?: string |
104 | address2?: string |
105 | city?: string |
106 | country?: string |
107 | county?: string |
108 | emailAddress?: string |
109 | mobilePhone?: string |
110 | phone?: string |
111 | postalCode?: string |
112 | state?: string |
113 | }[] |
114 | isEmployee943?: false | true |
115 | isSmoker?: false | true |
116 | lastName?: string |
117 | localTax?: { |
118 | exemptions?: number |
119 | exemptions2?: number |
120 | filingStatus?: string |
121 | residentPSD?: string |
122 | taxCode?: string |
123 | workPSD?: string |
124 | }[] |
125 | mainDirectDeposit?: { |
126 | accountNumber?: string |
127 | accountType?: string |
128 | isSkipPreNote?: false | true |
129 | preNoteDate?: string |
130 | routingNumber?: string |
131 | }[] |
132 | maritalStatus?: string |
133 | medExemptReason?: string |
134 | middleName?: string |
135 | nonPrimaryStateTax?: { |
136 | amount?: number |
137 | deductionsAmount?: number |
138 | dependentsAmount?: number |
139 | exemptions?: number |
140 | exemptions2?: number |
141 | filingStatus?: string |
142 | higherRate?: false | true |
143 | otherIncomeAmount?: number |
144 | percentage?: number |
145 | reciprocityCode?: string |
146 | specialCheckCalc?: number |
147 | taxCalculationCode?: number |
148 | taxCode?: number |
149 | w4FormYear?: number |
150 | }[] |
151 | preferredName?: string |
152 | primaryPayRate?: { |
153 | baseRate?: number |
154 | changeReason?: string |
155 | defaultHours?: number |
156 | effectiveDate?: string |
157 | isAutoPay?: false | true |
158 | payFrequency?: string |
159 | payGrade?: string |
160 | payType?: string |
161 | ratePer?: string |
162 | salary?: number |
163 | }[] |
164 | primaryStateTax?: { |
165 | amount?: number |
166 | deductionsAmount?: number |
167 | dependentsAmount?: number |
168 | exemptions?: number |
169 | exemptions2?: number |
170 | filingStatus?: string |
171 | higherRate?: false | true |
172 | otherIncomeAmount?: number |
173 | percentage?: number |
174 | specialCheckCalc?: string |
175 | taxCalculationCode?: string |
176 | taxCode?: string |
177 | w4FormYear?: number |
178 | }[] |
179 | priorLastName?: string |
180 | salutation?: string |
181 | sitwExemptReason?: string |
182 | ssExemptReason?: string |
183 | ssn?: string |
184 | status?: { |
185 | adjustedSeniorityDate?: string |
186 | changeReason?: string |
187 | effectiveDate?: string |
188 | employeeStatus?: string |
189 | hireDate?: string |
190 | isEligibleForRehire?: string |
191 | }[] |
192 | suffix?: string |
193 | suiExemptReason?: string |
194 | suiState?: string |
195 | taxDistributionCode1099R?: string |
196 | taxForm?: string |
197 | veteranDescription?: string |
198 | webTime?: { |
199 | badgeNumber?: string |
200 | chargeRate?: number |
201 | isTimeLaborEnabled?: false | true |
202 | } |
203 | workAddress?: { |
204 | address1?: string |
205 | address2?: string |
206 | city?: string |
207 | country?: string |
208 | county?: string |
209 | emailAddress?: string |
210 | mobilePhone?: string |
211 | pager?: string |
212 | phone?: string |
213 | phoneExtension?: string |
214 | postalCode?: string |
215 | state?: string |
216 | }[] |
217 | workEligibility?: { |
218 | alienOrAdmissionDocumentNumber?: string |
219 | attestedDate?: string |
220 | countryOfIssuance?: string |
221 | foreignPassportNumber?: string |
222 | i94AdmissionNumber?: string |
223 | i9DateVerified?: string |
224 | i9Notes?: string |
225 | isI9Verified?: false | true |
226 | isSsnVerified?: false | true |
227 | ssnDateVerified?: string |
228 | ssnNotes?: string |
229 | visaType?: string |
230 | workAuthorization?: string |
231 | workUntil?: string |
232 | }[] |
233 | } |
234 | ) { |
235 | const url = new URL( |
236 | `https://dc1prodgwext.paylocity.com/api/v2/weblinkstaging/companies/${companyId}/employees/newemployees` |
237 | ) |
238 |
|
239 | const response = await fetch(url, { |
240 | method: 'POST', |
241 | headers: { |
242 | 'Content-Type': 'application/json', |
243 | Authorization: |
244 | 'Bearer ' + |
245 | (await getOAuthToken(auth, 'https://dc1prodgwext.paylocity.com/public/security/v1/token')) |
246 | }, |
247 | body: JSON.stringify(body) |
248 | }) |
249 | if (!response.ok) { |
250 | const text = await response.text() |
251 | throw new Error(`${response.status} ${text}`) |
252 | } |
253 | return await response.json() |
254 | } |
255 |
|
256 | async function getOAuthToken(auth: Paylocity, tokenUrl: string): Promise<string> { |
257 | const params = new URLSearchParams({ |
258 | grant_type: 'client_credentials', |
259 | client_id: auth.clientId, |
260 | client_secret: auth.clientSecret |
261 | }) |
262 |
|
263 | const response = await fetch(tokenUrl, { |
264 | method: 'POST', |
265 | headers: { |
266 | Authorization: 'Basic ' + btoa(`${auth.clientId}:${auth.clientSecret}`), |
267 | 'Content-Type': 'application/x-www-form-urlencoded' |
268 | }, |
269 | body: params.toString() |
270 | }) |
271 |
|
272 | if (!response.ok) { |
273 | const text = await response.text() |
274 | throw new Error(`OAuth token request failed: ${response.status} ${text}`) |
275 | } |
276 |
|
277 | const data = await response.json() |
278 | return data.access_token |
279 | } |
280 |
|