Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion example/src/ContractorOnboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import Flag from 'react-flagpack';
import React, { useState } from 'react';
import { RemoteFlows } from './RemoteFlows';
import { getUrlParam } from './utils/urlState';
import { AlertError } from './AlertError';
import { ReviewContractorOnboardingStep } from './ReviewContractorOnboardingStep';
import { PricingPlanCard } from './components/PricingPlanCard';
Expand Down Expand Up @@ -821,7 +822,9 @@ export const ContractorOnboardingWithProps = ({
export const ContractorOnboardingForm = () => {
const [formData, setFormData] = useState<ContractorOnboardingFormData>({
employmentId:
import.meta.env.VITE_CONTRACTOR_MANAGEMENT_EMPLOYMENT_ID || '', // use your own employment ID
getUrlParam('employmentId') ||
import.meta.env.VITE_CONTRACTOR_MANAGEMENT_EMPLOYMENT_ID ||
'', // use your own employment ID
externalId: '',
partnerExternalId: '',
});
Expand Down
104 changes: 102 additions & 2 deletions scripts/seed-onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@
* npm run seed:onboarding -- --country=DEU
* npm run seed:onboarding -- --country=ESP --basic-info-version=4
*
* Pass --type=contractor to instead create a contractor employment from the
* contractor_basic_information schema and stop there, mirroring the
* basic_information step of src/flows/ContractorOnboarding/hooks.tsx.
* ir35 (GBR) and nationality_status (SAU/KWT/OMN/QAT/BHR) aren't in that
* schema - ContractorOnboarding's jsfModify adds them client-side and the
* hook writes them to the contractor contract document after creating the
* employment - so this does the same with fixed answers that avoid the IR35
* SDS upload and the non-national warning.
*
* npm run seed:onboarding -- --country=GBR --type=contractor --env=sandbox
*
* By default this proxies through a locally running `example` dev server
* (BASE_URL, `example/.env`'s VITE_REMOTE_GATEWAY decides which gateway that
* is - easy to lose track of).
Expand Down Expand Up @@ -89,7 +100,13 @@ const stringArg = (key: string): string | undefined => {
return typeof value === 'string' ? value : undefined;
};
const COUNTRY = (stringArg('country') || 'DEU').toUpperCase();
const BASIC_INFO_VERSION = Number(stringArg('basic-info-version') || 4);
const TYPE = stringArg('type') || 'employee';
if (TYPE !== 'employee' && TYPE !== 'contractor') {
throw new Error(`--type must be employee or contractor (got ${TYPE}).`);
}
const BASIC_INFO_VERSION = Number(
stringArg('basic-info-version') || (TYPE === 'contractor' ? 1 : 4),
);
if ('env' in args && stringArg('env') === undefined) {
throw new Error(
'--env requires a value, e.g. --env=sandbox (got a bare --env flag).',
Expand Down Expand Up @@ -206,7 +223,86 @@ async function findSafeStartDate(): Promise<string> {
return pickSafeDate(holidayDates);
}

async function main() {
const CONTRACTOR_NATIONALITY_COUNTRIES = ['SAU', 'KWT', 'OMN', 'QAT', 'BHR'];

function contractorContractDocumentSeed(): Record<string, string> | undefined {
if (COUNTRY === 'GBR') return { ir_35: 'exempt' };
if (CONTRACTOR_NATIONALITY_COUNTRIES.includes(COUNTRY)) {
return { nationality: 'national' };
}
return undefined;
}

async function seedContractor() {
console.log(`Fetching contractor_basic_information schema for ${COUNTRY}...`);
const basicInfoSchema = await fetchSchema(
'contractor_basic_information',
BASIC_INFO_VERSION,
);
const startDate = await findSafeStartDate();
const { values: basicInformation, skipped } = fillSchema(basicInfoSchema, {
provisional_start_date: startDate,
});
console.log(
'basic_information payload:',
JSON.stringify(basicInformation, null, 2),
);
if (skipped.length) {
console.log('Skipped (unfillable) fields:', skipped.join(', '));
}

console.log('\nCreating contractor employment...');
const created = await api<{ data?: { employment?: { id?: string } } }>(
'POST',
'/v1/employments',
{
query: { json_schema_version: BASIC_INFO_VERSION },
body: {
basic_information: basicInformation,
type: 'contractor',
country_code: COUNTRY,
},
},
);
const employmentId = created?.data?.employment?.id;
if (!employmentId) {
throw new Error(
`Could not find employment id in response: ${JSON.stringify(created)}`,
);
}
console.log(`Employment created: ${employmentId}`);

const contractDocument = contractorContractDocumentSeed();
if (contractDocument) {
console.log(
`\nSetting ${Object.keys(contractDocument).join(', ')} on the contract document...`,
);
await api(
'POST',
`/v1/contractors/employments/${employmentId}/contract-documents`,
{ body: { contract_document: contractDocument } },
);
}

console.log(
`\nDone. Contractor employment ${employmentId} for ${COUNTRY} has basic_information filled in.`,
);
const appUrl = process.env.VITE_APP_URL || (ENV ? undefined : BASE_URL);
if (appUrl) {
console.log(
`\nOpen this link (Employment ID is prefilled via ?employmentId=):\n\n` +
` ${appUrl}/?demo=contract-onboarding&employmentId=${employmentId}\n`,
);
} else {
console.log(
`\nOpen your app's contractor onboarding demo and enter this Employment ID ` +
`(?employmentId=${employmentId} also works as a query param).\n` +
`Tip: set VITE_APP_URL=<your deployed app URL> in .env.${ENV} to get a ready-to-click link next time.`,
Comment thread
cursor[bot] marked this conversation as resolved.
);
}
}

async function seedEmployee() {
console.log(`Fetching employment_basic_information schema for ${COUNTRY}...`);
const basicInfoSchema = await fetchSchema(
'employment_basic_information',
Expand Down Expand Up @@ -311,6 +407,10 @@ async function main() {
}
}

function main() {
return TYPE === 'contractor' ? seedContractor() : seedEmployee();
}

main().catch((err: unknown) => {
console.error('\nFailed:', err instanceof Error ? err.message : err);
if (err instanceof ApiError && err.body) {
Expand Down
Loading