diff --git a/components/riskadvisor/actions/create-client/create-client.mjs b/components/riskadvisor/actions/create-client/create-client.mjs new file mode 100644 index 0000000000000..ca8a2dcc01eae --- /dev/null +++ b/components/riskadvisor/actions/create-client/create-client.mjs @@ -0,0 +1,102 @@ +import riskadvisor from "../../riskadvisor.app.mjs"; + +export default { + key: "riskadvisor-create-client", + name: "Create Client", + description: "Create a new client in RiskAdvisor. [See the documentation](https://api.riskadvisor.insure/clients#create-a-client)", + version: "0.0.1", + type: "action", + props: { + riskadvisor, + firstName: { + propDefinition: [ + riskadvisor, + "firstName", + ], + }, + lastName: { + propDefinition: [ + riskadvisor, + "lastName", + ], + }, + phoneNumber: { + propDefinition: [ + riskadvisor, + "phoneNumber", + ], + }, + email: { + propDefinition: [ + riskadvisor, + "email", + ], + }, + middleName: { + propDefinition: [ + riskadvisor, + "middleName", + ], + }, + suffix: { + propDefinition: [ + riskadvisor, + "suffix", + ], + }, + dateOfBirth: { + propDefinition: [ + riskadvisor, + "dateOfBirth", + ], + }, + contactPreference: { + propDefinition: [ + riskadvisor, + "contactPreference", + ], + }, + gender: { + propDefinition: [ + riskadvisor, + "gender", + ], + }, + education: { + propDefinition: [ + riskadvisor, + "education", + ], + }, + occupation: { + propDefinition: [ + riskadvisor, + "occupation", + ], + }, + }, + async run({ $ }) { + const response = await this.riskadvisor.createClient({ + data: { + first_name: this.firstName, + last_name: this.lastName, + phone_number: this.phoneNumber, + email: this.email, + middle_name: this.middleName, + suffix: this.suffix, + date_of_birth: this.dateOfBirth, + contact_preference: this.contactPreference, + gender: this.gender, + education: this.education, + occupation: this.occupation, + }, + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully created client with ID ${response.id}.`); + } + + return response; + }, +}; diff --git a/components/riskadvisor/actions/create-risk-profile/create-risk-profile.mjs b/components/riskadvisor/actions/create-risk-profile/create-risk-profile.mjs new file mode 100644 index 0000000000000..a863a4e80955c --- /dev/null +++ b/components/riskadvisor/actions/create-risk-profile/create-risk-profile.mjs @@ -0,0 +1,51 @@ +import riskadvisor from "../../riskadvisor.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "riskadvisor-create-risk-profile", + name: "Create Risk Profile", + description: "Creates a risk profile in RiskAdvisor. [See the documentation](https://api.riskadvisor.insure/risk-profiles#create-a-risk-profile)", + version: "0.0.1", + type: "action", + props: { + riskadvisor, + insuranceType: { + type: "string", + label: "Insurance Type", + description: "The type of insurance", + options: constants.INSURANCE_TYPES, + }, + clientId: { + propDefinition: [ + riskadvisor, + "clientId", + ], + description: "Unique identifier for the client in the risk profile.", + }, + coClientId: { + propDefinition: [ + riskadvisor, + "clientId", + ], + label: "Co-Client", + description: "Unique identifier for the other client in the risk profile.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.riskadvisor.createRiskProfile({ + data: { + insurance_type: this.insuranceType, + client_id: this.clientId, + co_client_id: this.coClientId, + }, + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully created risk profile with ID ${response.id}.`); + } + + return response; + }, +}; diff --git a/components/riskadvisor/actions/update-client/update-client.mjs b/components/riskadvisor/actions/update-client/update-client.mjs new file mode 100644 index 0000000000000..345775989ce4b --- /dev/null +++ b/components/riskadvisor/actions/update-client/update-client.mjs @@ -0,0 +1,131 @@ +import riskadvisor from "../../riskadvisor.app.mjs"; +import lodash from "lodash"; + +export default { + key: "riskadvisor-update-client", + name: "Update Client", + description: "Updates an existing in RiskAdvisor. [See the documentation](https://api.riskadvisor.insure/clients#update-a-client)", + version: "0.0.1", + type: "action", + props: { + riskadvisor, + clientId: { + propDefinition: [ + riskadvisor, + "clientId", + ], + }, + firstName: { + propDefinition: [ + riskadvisor, + "firstName", + ], + optional: true, + }, + lastName: { + propDefinition: [ + riskadvisor, + "lastName", + ], + optional: true, + }, + phoneNumber: { + propDefinition: [ + riskadvisor, + "phoneNumber", + ], + optional: true, + }, + email: { + propDefinition: [ + riskadvisor, + "email", + ], + optional: true, + }, + middleName: { + propDefinition: [ + riskadvisor, + "middleName", + ], + }, + suffix: { + propDefinition: [ + riskadvisor, + "suffix", + ], + }, + dateOfBirth: { + propDefinition: [ + riskadvisor, + "dateOfBirth", + ], + }, + contactPreference: { + propDefinition: [ + riskadvisor, + "contactPreference", + ], + }, + gender: { + propDefinition: [ + riskadvisor, + "gender", + ], + }, + education: { + propDefinition: [ + riskadvisor, + "education", + ], + }, + occupation: { + propDefinition: [ + riskadvisor, + "occupation", + ], + }, + }, + methods: { + // getClient endpoint "/api/clients/:id" not yet implemented in the RiskAdvisor API + // todo: update to use getClient endpoint when implemented + async getClient(clientId) { + const clients = this.riskadvisor.paginate({ + resourceFn: this.riskadvisor.listClients, + }); + + for await (const client of clients) { + if (client.id === clientId) { + return client; + } + } + }, + }, + async run({ $ }) { + const client = await this.getClient(this.clientId); + + const response = await this.riskadvisor.updateClient({ + clientId: this.clientId, + data: lodash.pickBy({ + first_name: this.firstName || client.first_name, + last_name: this.lastName || client.last_name, + phone_number: this.phoneNumber || client.phone_number, + email: this.email || client.email, + middle_name: this.middleName, + suffix: this.suffix, + date_of_birth: this.dateOfBirth, + contact_preference: this.contactPreference, + gender: this.gender, + education: this.education, + occupation: this.occupation, + }), + $, + }); + + if (response?.id) { + $.export("$summary", `Successfully updated client with ID ${response.id}.`); + } + + return response; + }, +}; diff --git a/components/riskadvisor/common/constants.mjs b/components/riskadvisor/common/constants.mjs new file mode 100644 index 0000000000000..426f08a0a9919 --- /dev/null +++ b/components/riskadvisor/common/constants.mjs @@ -0,0 +1,13 @@ +const DEFAULT_LIMIT = 25; + +const INSURANCE_TYPES = [ + "home", + "auto", + "umbrella", + "home_auto", +]; + +export default { + DEFAULT_LIMIT, + INSURANCE_TYPES, +}; diff --git a/components/riskadvisor/package.json b/components/riskadvisor/package.json index e5f668f7eef7d..a49007109b25d 100644 --- a/components/riskadvisor/package.json +++ b/components/riskadvisor/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/riskadvisor", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream RiskAdvisor Components", "main": "riskadvisor.app.mjs", "keywords": [ @@ -11,5 +11,9 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "lodash": "^4.17.21" } -} \ No newline at end of file +} diff --git a/components/riskadvisor/riskadvisor.app.mjs b/components/riskadvisor/riskadvisor.app.mjs index 4d55990056670..df527bbc55dc2 100644 --- a/components/riskadvisor/riskadvisor.app.mjs +++ b/components/riskadvisor/riskadvisor.app.mjs @@ -1,11 +1,175 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "riskadvisor", - propDefinitions: {}, + propDefinitions: { + clientId: { + type: "integer", + label: "Client", + description: "Identifier of the client to update", + async options({ prevContext }) { + const params = { + limit: constants.DEFAULT_LIMIT, + }; + if (prevContext?.startingAfter) { + params.starting_after = prevContext.startingAfter; + } + const { data } = await this.listClients({ + params, + }); + const options = data?.map(({ + id: value, first_name, last_name, + }) => ({ + value, + label: `${first_name} ${last_name}`, + })) || []; + return { + options, + context: { + startingAfter: data?.length + ? data[data.length - 1].id + : null, + }, + }; + }, + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the client.", + }, + lastName: { + type: "string", + label: "Last Name", + description: "The last name of the client.", + }, + phoneNumber: { + type: "string", + label: "Phone Number", + description: "The phone number for the client.", + }, + email: { + type: "string", + label: "Email", + description: "The email address of the client.", + }, + middleName: { + type: "string", + label: "Middle Name", + description: "The middle name of the client.", + optional: true, + }, + suffix: { + type: "string", + label: "Suffix", + description: "The suffix of the client.", + optional: true, + }, + dateOfBirth: { + type: "string", + label: "Date of Birth", + description: "The date of birth of the client.", + optional: true, + }, + contactPreference: { + type: "string", + label: "Contact Preference", + description: "The client's preferred contact method (i.e. phone or email).", + optional: true, + }, + gender: { + type: "string", + label: "Gender", + description: "The client's gender.", + optional: true, + }, + education: { + type: "string", + label: "Education", + description: "The client's education level.", + optional: true, + }, + occupation: { + type: "string", + label: "Occupation", + description: "The client's occupation.", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://app.riskadvisor.insure/api"; + }, + _headers() { + return { + Authorization: `Bearer ${this.$auth.api_token}`, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + listClients(args = {}) { + return this._makeRequest({ + path: "/clients", + ...args, + }); + }, + createClient(args = {}) { + return this._makeRequest({ + path: "/clients", + method: "POST", + ...args, + }); + }, + createRiskProfile(args = {}) { + return this._makeRequest({ + path: "/risk-profiles", + method: "POST", + ...args, + }); + }, + updateClient({ + clientId, ...args + }) { + return this._makeRequest({ + path: `/clients/${clientId}`, + method: "PUT", + ...args, + }); + }, + async *paginate({ + resourceFn, + args = {}, + }) { + args = { + ...args, + params: { + ...args.params, + limit: constants.DEFAULT_LIMIT, + }, + }; + let total = 0; + do { + const { data } = await resourceFn(args); + if (!data?.length) { + return; + } + for (const item of data) { + yield item; + } + total = data.length; + args.params.starting_after = data[total - 1].id; + } while (total === args.params.limit); }, }, -}; \ No newline at end of file +}; diff --git a/components/riskadvisor/sources/client-updated/client-updated.mjs b/components/riskadvisor/sources/client-updated/client-updated.mjs new file mode 100644 index 0000000000000..d24a5772bd22d --- /dev/null +++ b/components/riskadvisor/sources/client-updated/client-updated.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "riskadvisor-client-updated", + name: "Client Updated", + description: "Emit new event each time a client is updated in RiskAdvisor. [See the documentation](https://api.riskadvisor.insure/clients#list-all-clients)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getTsField() { + return "updated_at"; + }, + getResourceFn() { + return this.riskadvisor.listClients; + }, + generateMeta(client) { + const ts = Date.parse(client[this.getTsField()]); + return { + id: `${client.id}${ts}`, + summary: `Client "${client.first_name} ${client.last_name}" Updated`, + ts, + }; + }, + }, +}; diff --git a/components/riskadvisor/sources/common/base.mjs b/components/riskadvisor/sources/common/base.mjs new file mode 100644 index 0000000000000..e5a5bc1929a1c --- /dev/null +++ b/components/riskadvisor/sources/common/base.mjs @@ -0,0 +1,66 @@ +import riskadvisor from "../../riskadvisor.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + props: { + riskadvisor, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + hooks: { + async deploy() { + await this.processEvents(25); + }, + }, + methods: { + _getLastTs() { + return this.db.get("lastTs") || 0; + }, + _setLastTs(lastTs) { + this.db.set("lastTs", lastTs); + }, + getTsField() { + throw new Error("getTsField is not implemented"); + }, + gettResourceFn() { + throw new Error("gettResourceFn is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + async processEvents(max) { + const lastTs = this._getLastTs(); + let maxTs = lastTs; + + const items = this.riskadvisor.paginate({ + resourceFn: this.getResourceFn(), + }); + + let count = 0; + for await (const item of items) { + const ts = Date.parse(item[this.getTsField()]); + if (ts > lastTs) { + const meta = this.generateMeta(item); + this.$emit(item, meta); + if (ts > maxTs) { + maxTs = ts; + } + count++; + if (max && count >= max) { + break; + } + } + } + + this._setLastTs(maxTs); + }, + }, + async run() { + await this.processEvents(); + }, +}; diff --git a/components/riskadvisor/sources/new-client-created/new-client-created.mjs b/components/riskadvisor/sources/new-client-created/new-client-created.mjs new file mode 100644 index 0000000000000..e6b60ac6af4da --- /dev/null +++ b/components/riskadvisor/sources/new-client-created/new-client-created.mjs @@ -0,0 +1,27 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "riskadvisor-new-client-created", + name: "New Client Created", + description: "Emit new event each time a new client is created in RiskAdvisor. [See the documentation](https://api.riskadvisor.insure/clients#list-all-clients)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getTsField() { + return "created_at"; + }, + getResourceFn() { + return this.riskadvisor.listClients; + }, + generateMeta(client) { + return { + id: client.id, + summary: `Client "${client.first_name} ${client.last_name}" Created`, + ts: Date.parse(client[this.getTsField()]), + }; + }, + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52ba58dac46b7..b9f79ca79a103 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -856,6 +856,9 @@ importers: components/cheddar: specifiers: {} + components/chmeetings: + specifiers: {} + components/circl_hash_lookup: specifiers: {} @@ -4833,7 +4836,12 @@ importers: '@pipedream/platform': 1.5.1 components/riskadvisor: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + lodash: ^4.17.21 + dependencies: + '@pipedream/platform': 1.5.1 + lodash: 4.17.21 components/rkvst: specifiers: {} @@ -5291,6 +5299,9 @@ importers: dependencies: '@pipedream/platform': 0.10.0 + components/signable: + specifiers: {} + components/signaturely: specifiers: '@pipedream/platform': ^1.5.1