Last active
November 28, 2023 16:26
-
-
Save izakfilmalter/afe3444d81d3b79d42f0eb7a5c5b6e9d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { IO } from '@trigger.dev/sdk' | |
import { Option, pipe, ReadonlyArray, String } from 'effect' | |
import qs from 'qs' | |
import type { z } from 'zod' | |
import type { PlanningCenterDonation } from '@steepleinc/shared' | |
import { asyncNoOp } from '@steepleinc/shared' | |
import { transformPlanningCenterDonation } from '../../helpers/planningCenterTransformers' | |
import type { triggerRouter } from '../../types' | |
import { saveDonationsTask } from '../replicache/saveDonations.task' | |
import { getPlanningCenterAPITask } from './getPlanningCenterAPI.task' | |
import { updateSyncStatusTask } from './updateSyncStatus.task' | |
const importNextPage = (params: { | |
nextUrl?: string | |
io: IO | |
orgId: string | |
alreadyImportedIds: ReadonlyArray<string> | |
}) => { | |
const { nextUrl, io, orgId, alreadyImportedIds } = params | |
return pipe( | |
nextUrl, | |
Option.fromNullable, | |
Option.match({ | |
onNone: asyncNoOp, | |
onSome: async (x) => { | |
const { offset } = qs.parse( | |
pipe(x, String.split('?'), ReadonlyArray.lastNonEmpty), | |
) as { | |
include: string | |
offset: string | |
order: string | |
per_page: string | |
} | |
return await importPlanningCenterDonationsTaskChain({ | |
orgId, | |
url: x, | |
alreadyImportedIds, | |
io, | |
offset, | |
}) | |
}, | |
}), | |
) | |
} | |
export const importPlanningCenterDonationsTaskChain = async ( | |
params: { | |
io: IO | |
offset: string | |
} & z.infer<typeof triggerRouter.importPlanningCenterDonations.schema>, | |
) => { | |
const { | |
orgId, | |
url = `https://api.planningcenteronline.com/giving/v2/donations?${qs.stringify( | |
{ per_page: 100 }, | |
{ arrayFormat: 'comma' }, | |
)}`, | |
alreadyImportedIds = [], | |
io, | |
offset, | |
} = params | |
// Toggle syncStatus to syncing. | |
await io.runTask( | |
...updateSyncStatusTask({ | |
taskId: `startSyncingDonations-${offset}`, | |
orgId, | |
key: 'donations', | |
status: { tag: 'syncing' }, | |
}), | |
) | |
// Get donations. | |
const donationOpt = await io | |
.runTask( | |
...getPlanningCenterAPITask<Array<PlanningCenterDonation>, null>({ | |
url, | |
orgId, | |
setSyncStatusOnFailure: { | |
orgId, | |
key: 'donations', | |
status: { | |
tag: 'error', | |
error: `It looks like something when wrong trying to sync your Donations. Contact Steeple support to get this resolved.`, | |
}, | |
}, | |
}), | |
) | |
.then((x) => | |
pipe( | |
x, | |
Option.fromNullable, | |
Option.map((y) => ({ | |
donations: pipe( | |
y.data, | |
ReadonlyArray.map((z) => | |
transformPlanningCenterDonation({ donation: z }), | |
), | |
), | |
nextUrl: y.links.next, | |
})), | |
), | |
) | |
await io.logger.log( | |
`${offset}: Got donations: ${pipe( | |
donationOpt, | |
Option.match({ | |
onNone: () => 'No Donations', | |
onSome: (x) => x.donations.length, | |
}), | |
)}`, | |
) | |
await pipe( | |
donationOpt, | |
Option.match({ | |
// Failed to get donations | |
onNone: asyncNoOp, | |
// Get donations | |
onSome: async ({ donations, nextUrl }) => { | |
// Save donations. | |
await io.runTask(...saveDonationsTask({ orgId, donations, offset })) | |
// Import next page if we have a next page. | |
await importNextPage({ | |
nextUrl, | |
orgId, | |
io, | |
alreadyImportedIds: pipe( | |
alreadyImportedIds, | |
ReadonlyArray.appendAll( | |
pipe( | |
donations, | |
ReadonlyArray.map((y) => y.id), | |
), | |
), | |
), | |
}) | |
await pipe( | |
nextUrl, | |
Option.fromNullable, | |
Option.match({ | |
// No more donations. Clean up time. | |
onNone: async () => { | |
// Finished syncing | |
await io.runTask( | |
...updateSyncStatusTask({ | |
taskId: `finishSyncingDonations-${offset}`, | |
orgId, | |
key: 'donations', | |
status: { tag: 'done' }, | |
}), | |
) | |
}, | |
// More donations. NoOp | |
onSome: asyncNoOp, | |
}), | |
) | |
}, | |
}), | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment