From ef9a3d1244333793f5bac525d8cc865e5d672794 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Tue, 23 Apr 2024 13:45:38 +0200 Subject: [PATCH 1/8] added new invoice trigger --- package.json | 2 +- src/authentication.ts | 2 +- src/index.ts | 2 + .../triggers/triggerInvoiceCreated.test.ts | 126 ++++++++++++++++++ src/triggers/triggerInvoiceCreated.ts | 80 +++++++++++ src/types/api-responses.d.ts | 51 +++++++ src/types/outputs.d.ts | 7 +- src/utils/api-to-output.ts | 13 ++ src/utils/api.ts | 24 ++++ src/utils/samples.ts | 75 +++++++++++ 10 files changed, 379 insertions(+), 3 deletions(-) create mode 100644 src/test/triggers/triggerInvoiceCreated.test.ts create mode 100644 src/triggers/triggerInvoiceCreated.ts diff --git a/package.json b/package.json index 0c9aa33..1abc945 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cobot-zapier", - "version": "2.1.0", + "version": "2.2.0", "description": "", "main": "index.js", "scripts": { diff --git a/src/authentication.ts b/src/authentication.ts index 0b64577..91ee3d6 100644 --- a/src/authentication.ts +++ b/src/authentication.ts @@ -7,7 +7,7 @@ const AUTHORIZE_URL = `${BASE_URL}/oauth/authorize`; const ACCESS_TOKEN_URL = `${BASE_URL}/oauth/access_token`; const TEST_AUTH_URL = `${BASE_URL}/api/user`; const scopes = - "read read_admins read_bookings read_events read_external_bookings read_memberships read_resources read_spaces read_user write_activities write_subscriptions"; + "read read_admins read_bookings read_events read_external_bookings read_invoices read_memberships read_resources read_spaces read_user write_activities write_subscriptions"; const getAccessToken = async ( z: ZObject, diff --git a/src/index.ts b/src/index.ts index 72e98ac..1b9e2ab 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ import triggerMembershipPlanChanged from "./triggers/triggerMembershipPlanChange import triggerExternalBooking from "./triggers/triggerExternalBookingCreated"; import getSubdomains from "./triggers/dropdowns/getSubdomains"; import triggerEventPublished from "./triggers/triggerEventPublished"; +import triggerInvoiceCreated from "./triggers/triggerInvoiceCreated"; const { version } = require("../package.json"); @@ -32,6 +33,7 @@ export default { [triggerMembershipConfirmed.key]: triggerMembershipConfirmed, [triggerMembershipPlanChanged.key]: triggerMembershipPlanChanged, [triggerEventPublished.key]: triggerEventPublished, + [triggerInvoiceCreated.key]: triggerInvoiceCreated, [triggerExternalBooking.key]: triggerExternalBooking, // Lists for dropdowns [getSubdomains.key]: getSubdomains, diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts new file mode 100644 index 0000000..7669e36 --- /dev/null +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -0,0 +1,126 @@ +import { createAppTester } from "zapier-platform-core"; +import * as nock from "nock"; +import App from "../../index"; +import { + prepareBundle, + prepareMocksForWebhookSubscribeTest, +} from "../utils/prepareMocksForWebhookSubscribeTest"; +import triggerInvoiceCreated from "../../triggers/triggerInvoiceCreated"; +import { HookTrigger } from "../../types/trigger"; +import { + UserApiResponse, + InvoiceApiResponse, + BaseInvoiceProperties, +} from "../../types/api-responses"; + +const appTester = createAppTester(App); +nock.disableNetConnect(); +const trigger = App.triggers[triggerInvoiceCreated.key] as HookTrigger; + +afterEach(() => nock.cleanAll()); + +describe("triggerInvoiceCreated", () => { + it("creates new webhook through CM API upon subscribe", async () => { + const bundle = prepareMocksForWebhookSubscribeTest( + triggerInvoiceCreated.key, + ); + const subscribe = trigger.operation.performSubscribe; + + const result = await appTester(subscribe as any, bundle as any); + + expect(result).toMatchInlineSnapshot(` +{ + "url": "https://trial.cobot.me/api/event/callback", +} +`); + }); + + it("lists recent invoices", async () => { + const bundle = prepareBundle(); + const userResponse: UserApiResponse = { + included: [{ id: "space-1", attributes: { subdomain: "trial" } }], + }; + const attributes: BaseInvoiceProperties = { + invoiceDate: "2024-12-20T06:22:29+01:00", + paidStatus: "paid", + dueDate: "2024-12-30T08:22:29+01:00", + number: "1", + sentStatus: "sent", + taxIdName: "taxIdName", + canCharge: true, + recipientAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + senderAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + items: [ + { + description: "item 1", + quantity: "1", + paid: true, + accountingCode: null, + amount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + }, + ], + payableAmount: "100", + paidAmount: "100", + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + invoiceText: "invoiceText", + paidDate: "2024-12-22T06:22:29+01:00", + taxId: null, + chargeAt: null, + customerNumber: null, + notes: null, + }; + const invoiceResponse: InvoiceApiResponse = { + id: "1", + attributes, + relationships: { + membership: { + data: { + id: "membership-1", + }, + }, + }, + }; + + const scope = nock("https://api.cobot.me"); + scope.get("/user?include=adminOf").reply(200, userResponse); + scope + .get(/\/spaces\/space-1\/invoices/) + .reply(200, { data: [invoiceResponse] }); + + const listRecentEvents = trigger.operation.performList; + + const results = await appTester(listRecentEvents as any, bundle as any); + + expect(results).toStrictEqual([ + { + ...attributes, + id: "1", + membershipId: "membership-1", + }, + ]); + }); +}); diff --git a/src/triggers/triggerInvoiceCreated.ts b/src/triggers/triggerInvoiceCreated.ts new file mode 100644 index 0000000..7f59dfd --- /dev/null +++ b/src/triggers/triggerInvoiceCreated.ts @@ -0,0 +1,80 @@ +import { ZObject } from "zapier-platform-core"; +import { KontentBundle } from "../types/kontentBundle"; +import { + apiCallUrl, + listRecentInvoices, + subscribeHook, + unsubscribeHook, +} from "../utils/api"; +import { SubscribeBundleInputType } from "../types/subscribeType"; +import { getSubdomainField } from "../fields/getSudomainsField"; +import { invoiceSample } from "../utils/samples"; +import { InvoiceApiResponse } from "../types/api-responses"; +import { InvoiceOutput } from "../types/outputs"; +import { HookTrigger } from "../types/trigger"; +import { apiResponseToInvoiceOutput } from "../utils/api-to-output"; + +const hookLabel = "Invoice Created"; +const event = "created_invoice"; + +async function subscribeHookExecute( + z: ZObject, + bundle: KontentBundle, +) { + return subscribeHook(z, bundle, { + event, + callback_url: bundle.targetUrl ?? "", + }); +} + +async function unsubscribeHookExecute( + z: ZObject, + bundle: KontentBundle, +) { + const webhook = bundle.subscribeData; + return unsubscribeHook(z, bundle, webhook?.id ?? ""); +} + +async function parsePayload( + z: ZObject, + bundle: KontentBundle<{}>, +): Promise { + if (bundle.cleanedRequest) { + const invoice = (await apiCallUrl( + z, + bundle.cleanedRequest.url, + )) as InvoiceApiResponse; + return [apiResponseToInvoiceOutput(invoice)]; + } else { + return []; + } +} + +const trigger: HookTrigger = { + key: `${event}`, + noun: hookLabel, + display: { + label: hookLabel, + description: "Triggers when an invoice is created.", + }, + operation: { + type: "hook", + + inputFields: [getSubdomainField()], + + performSubscribe: subscribeHookExecute, + performUnsubscribe: unsubscribeHookExecute, + + perform: parsePayload, + performList: async ( + z: ZObject, + bundle: KontentBundle, + ): Promise => { + const invoices = await listRecentInvoices(z, bundle); + return invoices.map((invoice) => apiResponseToInvoiceOutput(invoice)); + }, + + sample: invoiceSample, + }, +}; +export default trigger; diff --git a/src/types/api-responses.d.ts b/src/types/api-responses.d.ts index c2de0e3..4869950 100644 --- a/src/types/api-responses.d.ts +++ b/src/types/api-responses.d.ts @@ -59,6 +59,57 @@ export type EventApiResponse = { }; }; +type Address = { + company: string | null; + name: string | null; + fullAddress: string | null; +}; + +type InvoiceItems = { + description: string; + paid: boolean; + quantity: string; + accountingCode: string | null; + amount: Amount; + totalAmount: Amount; +}; + +type Relationship = { + data: { + id: string; + }; +}; + +export type BaseInvoiceProperties = { + invoiceText: string | null; + invoiceDate: string; + paidDate: string | null; + paidStatus: "unpaid" | "paid" | "pending" | "canceled" | "writtenOff"; + dueDate: string; + number: string; + sentStatus: "sent" | "sending" | "unsent" | "failedToSend"; + taxId: string | null; + taxIdName: string; + chargeAt: string | null; + canCharge: boolean; + customerNumber: string | null; + recipientAddress: Address; + senderAddress: Address; + notes: string | null; + items: InvoiceItems[]; + payableAmount: string; + paidAmount: string; + totalAmount: Amount; +}; + +export type InvoiceApiResponse = { + id: string; + attributes: BaseInvoiceProperties; + relationships: { + membership: Relationship; + }; +}; + export type ExternalBookingStatus = "approved" | "pending" | "canceled"; export type ExternalBookingApiResponse = { diff --git a/src/types/outputs.d.ts b/src/types/outputs.d.ts index 9712533..3c2ebad 100644 --- a/src/types/outputs.d.ts +++ b/src/types/outputs.d.ts @@ -1,4 +1,4 @@ -import { ExternalBookingStatus } from "./api-responses"; +import { ExternalBookingStatus, BaseInvoiceProperties } from "./api-responses"; export type BookingOutput = { id: string; @@ -57,3 +57,8 @@ export type MembershipOutput = { plan_name: string; payment_method_name: string | null; }; + +export type InvoiceOutput = BaseInvoiceProperties & { + membershipId: string; + id: string; +}; diff --git a/src/utils/api-to-output.ts b/src/utils/api-to-output.ts index 9aca2aa..7b83462 100644 --- a/src/utils/api-to-output.ts +++ b/src/utils/api-to-output.ts @@ -2,12 +2,14 @@ import { BookingApiResponse, EventApiResponse, MembershipApiResponse, + InvoiceApiResponse, } from "../types/api-responses"; import { BookingOutput, EventOutput, ExternalBookingOutput, MembershipOutput, + InvoiceOutput, } from "../types/outputs"; import { ExternalBookingWithResourceApiResponse } from "./api"; @@ -25,6 +27,17 @@ export function apiResponseToMembershipOutput( }; } +export function apiResponseToInvoiceOutput( + invoice: InvoiceApiResponse, +): InvoiceOutput { + const attributes = invoice.attributes; + return { + ...attributes, + id: invoice.id, + membershipId: invoice.relationships.membership.data.id, + }; +} + export function apiResponseToEventOutput(event: EventApiResponse): EventOutput { const attributes = event.attributes; return { diff --git a/src/utils/api.ts b/src/utils/api.ts index 6f0f7a0..749f999 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -14,6 +14,7 @@ import { MembershipApiResponse, ResourceApiResponse, UserApiResponse, + InvoiceApiResponse, } from "../types/api-responses"; type Space = { @@ -142,6 +143,29 @@ export const getUserDetailV2 = async (z: ZObject): Promise => { return response.data; }; +export const listRecentInvoices = async ( + z: ZObject, + bundle: KontentBundle, +): Promise => { + const subdomain = bundle.inputData.subdomain; + const space = await spaceForSubdomain(z, subdomain); + if (!space) return []; + const spaceId = space.id; + const [from, to] = getDateRange(); + const response = await z.request({ + url: `https://api.cobot.me/spaces/${spaceId}/invoices`, + method: "GET", + headers: { + Accept: "application/vnd.api+json", + }, + params: { + "filter[from]": from, + "filter[to]": to, + }, + }); + return response.data.data; +}; + export const listRecentExternalBookings = async ( z: ZObject, bundle: KontentBundle, diff --git a/src/utils/samples.ts b/src/utils/samples.ts index e658b46..f81b6ea 100644 --- a/src/utils/samples.ts +++ b/src/utils/samples.ts @@ -3,6 +3,7 @@ import { EventOutput, ExternalBookingOutput, MembershipOutput, + InvoiceOutput, } from "../types/outputs"; export const bookingSample: BookingOutput = { @@ -62,3 +63,77 @@ export const membershipSample: MembershipOutput = { plan_name: "Full Time", payment_method_name: "Credit Card", }; + +export const invoiceSample: InvoiceOutput = { + id: "14c12f62ac8df98d29de357180d673e1", + invoiceText: "Thanks for your business!", + invoiceDate: "2019-01-10", + paidDate: null, + dueDate: "2019-01-10", + number: "CW-2019-100", + taxId: "DE12345", + taxIdName: "UID", + customerNumber: "100", + membershipId: "c9a99a71ac8df98d29de357180d273d3", + recipientAddress: { + name: "Jane Smith", + company: "Acme Inc.", + fullAddress: "2 Coworking Road", + }, + senderAddress: { + name: null, + company: "Coworking Ltd.", + fullAddress: "1 Coworking Road", + }, + notes: "Customer will pay later.", + items: [ + { + description: "2h meeting room", + quantity: "2.0", + accountingCode: "MTR-200", + paid: false, + amount: { + net: "20.0", + gross: "22.0", + currency: "EUR", + taxes: [ + { + name: "VAT", + rate: "10.0", + amount: "2.0", + }, + ], + }, + totalAmount: { + net: "40.0", + gross: "44.0", + currency: "EUR", + taxes: [ + { + name: "VAT", + rate: "10.0", + amount: "4.0", + }, + ], + }, + }, + ], + payableAmount: "44.0", + paidAmount: "0.0", + paidStatus: "unpaid", + chargeAt: "2019-01-02T11:00:00Z", + canCharge: true, + sentStatus: "unsent", + totalAmount: { + net: "40.0", + gross: "44.0", + currency: "EUR", + taxes: [ + { + name: "VAT", + rate: "10.0", + amount: "4.0", + }, + ], + }, +}; From a44f98c649a6daef7f444123e6b1486000ffa514 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Tue, 23 Apr 2024 15:48:45 +0200 Subject: [PATCH 2/8] added dateformat and a minor fix with relationship being null --- src/utils/api-to-output.ts | 2 +- src/utils/api.ts | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/utils/api-to-output.ts b/src/utils/api-to-output.ts index 7b83462..a6905b8 100644 --- a/src/utils/api-to-output.ts +++ b/src/utils/api-to-output.ts @@ -34,7 +34,7 @@ export function apiResponseToInvoiceOutput( return { ...attributes, id: invoice.id, - membershipId: invoice.relationships.membership.data.id, + membershipId: invoice.relationships.membership?.data?.id, }; } diff --git a/src/utils/api.ts b/src/utils/api.ts index 749f999..60b02ee 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -151,7 +151,7 @@ export const listRecentInvoices = async ( const space = await spaceForSubdomain(z, subdomain); if (!space) return []; const spaceId = space.id; - const [from, to] = getDateRange(); + const [from, to] = getDateRange("yyyy-MM-dd"); const response = await z.request({ url: `https://api.cobot.me/spaces/${spaceId}/invoices`, method: "GET", @@ -297,10 +297,12 @@ export const createActivity = async ( return object; }; -const getDateRange = (): [string, string] => { +const getDateRange = (format?: string): [string, string] => { const now = DateTime.now(); - const lastMonth = now.minus({ months: 1 }).toISO(); - const nextMonth = now.plus({ months: 1 }).toISO(); - - return [lastMonth, nextMonth]; + const lastMonth = now.minus({ months: 1 }); + const nextMonth = now.plus({ months: 1 }); + if (!format) { + return [lastMonth.toISO(), nextMonth.toISO()]; + } + return [lastMonth.toFormat(format), nextMonth.toFormat(format)]; }; From 36d81b407d324b2683e17d49e63e3f3d0743ebe9 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Wed, 24 Apr 2024 09:22:44 +0200 Subject: [PATCH 3/8] fixed field mismatch due to parsePayload using api1 --- src/triggers/triggerInvoiceCreated.ts | 12 +++++------- src/types/outputs.d.ts | 2 +- src/utils/api-to-output.ts | 2 +- src/utils/api.ts | 17 +++++++++++++++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/triggers/triggerInvoiceCreated.ts b/src/triggers/triggerInvoiceCreated.ts index 7f59dfd..f157a7c 100644 --- a/src/triggers/triggerInvoiceCreated.ts +++ b/src/triggers/triggerInvoiceCreated.ts @@ -1,10 +1,10 @@ import { ZObject } from "zapier-platform-core"; import { KontentBundle } from "../types/kontentBundle"; import { - apiCallUrl, listRecentInvoices, subscribeHook, unsubscribeHook, + getInvoiceFromApi2, } from "../utils/api"; import { SubscribeBundleInputType } from "../types/subscribeType"; import { getSubdomainField } from "../fields/getSudomainsField"; @@ -39,12 +39,10 @@ async function parsePayload( z: ZObject, bundle: KontentBundle<{}>, ): Promise { - if (bundle.cleanedRequest) { - const invoice = (await apiCallUrl( - z, - bundle.cleanedRequest.url, - )) as InvoiceApiResponse; - return [apiResponseToInvoiceOutput(invoice)]; + const invoiceId = bundle.cleanedRequest.url.split("/").pop(); + const response = await getInvoiceFromApi2(z, invoiceId); + if (response) { + return [apiResponseToInvoiceOutput(response)]; } else { return []; } diff --git a/src/types/outputs.d.ts b/src/types/outputs.d.ts index 3c2ebad..53d4881 100644 --- a/src/types/outputs.d.ts +++ b/src/types/outputs.d.ts @@ -59,6 +59,6 @@ export type MembershipOutput = { }; export type InvoiceOutput = BaseInvoiceProperties & { - membershipId: string; + membershipId?: string; id: string; }; diff --git a/src/utils/api-to-output.ts b/src/utils/api-to-output.ts index a6905b8..2c8738d 100644 --- a/src/utils/api-to-output.ts +++ b/src/utils/api-to-output.ts @@ -34,7 +34,7 @@ export function apiResponseToInvoiceOutput( return { ...attributes, id: invoice.id, - membershipId: invoice.relationships.membership?.data?.id, + membershipId: invoice.relationships?.membership?.data?.id ?? undefined, }; } diff --git a/src/utils/api.ts b/src/utils/api.ts index 60b02ee..7f90dcf 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -230,6 +230,23 @@ function notEmpty(value: TValue | null | undefined): value is TValue { export type ExternalBookingWithResourceApiResponse = ExternalBookingApiResponse & { resource: ResourceApiResponse }; +export const getInvoiceFromApi2 = async ( + z: ZObject, + invoiceId: string, +): Promise => { + const response = await z.request({ + url: `https://api.cobot.me/invoices/${invoiceId}`, + method: "GET", + headers: { + Accept: "application/vnd.api+json", + }, + }); + if (response.status === 404) { + return null; + } + return response.data.data as InvoiceApiResponse; +}; + export const getExternalBooking = async ( z: ZObject, bookingId: string, From b8ac431c18ae63541f3ae6ed5416bbe616bc4c34 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Wed, 24 Apr 2024 13:06:08 +0200 Subject: [PATCH 4/8] changes based on review --- .../triggers/triggerInvoiceCreated.test.ts | 86 +++++++++++++++++++ .../prepareMocksForWebhookSubscribeTest.ts | 3 + src/types/api-responses.d.ts | 4 +- src/utils/api.ts | 8 +- 4 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts index 7669e36..e9b9744 100644 --- a/src/test/triggers/triggerInvoiceCreated.test.ts +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -123,4 +123,90 @@ describe("triggerInvoiceCreated", () => { }, ]); }); + + it("triggers on new invoice", async () => { + const bundle = prepareBundle(); + const attributes: BaseInvoiceProperties = { + invoiceDate: "2024-12-20T06:22:29+01:00", + paidStatus: "paid", + dueDate: "2024-12-30T08:22:29+01:00", + number: "1", + sentStatus: "sent", + taxIdName: "taxIdName", + canCharge: true, + recipientAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + senderAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + items: [ + { + description: "item 1", + quantity: "1", + paid: true, + accountingCode: null, + amount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + }, + ], + payableAmount: "100", + paidAmount: "100", + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + invoiceText: "invoiceText", + paidDate: "2024-12-22T06:22:29+01:00", + taxId: null, + chargeAt: null, + customerNumber: null, + notes: null, + }; + const invoiceResponse: InvoiceApiResponse = { + id: "1", + attributes, + relationships: { + membership: { + data: { + id: "membership-1", + }, + }, + }, + }; + + const scope = nock("https://api.cobot.me"); + scope.get("/invoices/12345").reply(200, { data: invoiceResponse }); + + const results = await appTester( + triggerInvoiceCreated.operation.perform as any, + bundle as any, + ); + + expect(nock.isDone()).toBe(true); + + expect(results).toStrictEqual([ + { + ...attributes, + id: "1", + membershipId: "membership-1", + }, + ]); + }); }); diff --git a/src/test/utils/prepareMocksForWebhookSubscribeTest.ts b/src/test/utils/prepareMocksForWebhookSubscribeTest.ts index 3bb2b95..4bcb118 100644 --- a/src/test/utils/prepareMocksForWebhookSubscribeTest.ts +++ b/src/test/utils/prepareMocksForWebhookSubscribeTest.ts @@ -20,6 +20,9 @@ export const prepareBundle = (): KontentBundle => { ...mockBundle.inputData, subdomain: "trial", }, + cleanedRequest: { + url: "https://trial.cobot.me/api/event/12345", + }, targetUrl: "https://test-url.test", }; diff --git a/src/types/api-responses.d.ts b/src/types/api-responses.d.ts index 4869950..5d1d8cb 100644 --- a/src/types/api-responses.d.ts +++ b/src/types/api-responses.d.ts @@ -65,7 +65,7 @@ type Address = { fullAddress: string | null; }; -type InvoiceItems = { +type InvoiceItem = { description: string; paid: boolean; quantity: string; @@ -96,7 +96,7 @@ export type BaseInvoiceProperties = { recipientAddress: Address; senderAddress: Address; notes: string | null; - items: InvoiceItems[]; + items: InvoiceItem[]; payableAmount: string; paidAmount: string; totalAmount: Amount; diff --git a/src/utils/api.ts b/src/utils/api.ts index 7f90dcf..b25e7a0 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -151,7 +151,7 @@ export const listRecentInvoices = async ( const space = await spaceForSubdomain(z, subdomain); if (!space) return []; const spaceId = space.id; - const [from, to] = getDateRange("yyyy-MM-dd"); + const [from, to] = getDateRange(true); const response = await z.request({ url: `https://api.cobot.me/spaces/${spaceId}/invoices`, method: "GET", @@ -314,12 +314,12 @@ export const createActivity = async ( return object; }; -const getDateRange = (format?: string): [string, string] => { +const getDateRange = (useISODate = false): [string, string] => { const now = DateTime.now(); const lastMonth = now.minus({ months: 1 }); const nextMonth = now.plus({ months: 1 }); - if (!format) { + if (!useISODate) { return [lastMonth.toISO(), nextMonth.toISO()]; } - return [lastMonth.toFormat(format), nextMonth.toFormat(format)]; + return [lastMonth.toISODate(), nextMonth.toISODate()]; }; From f853231ef75900247c684691bfbb7e54748c13eb Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Wed, 24 Apr 2024 13:10:23 +0200 Subject: [PATCH 5/8] small refactor --- .../triggers/triggerInvoiceCreated.test.ts | 196 ++++++------------ 1 file changed, 66 insertions(+), 130 deletions(-) diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts index e9b9744..ae34bdc 100644 --- a/src/test/triggers/triggerInvoiceCreated.test.ts +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -13,6 +13,72 @@ import { BaseInvoiceProperties, } from "../../types/api-responses"; +const attributes: BaseInvoiceProperties = { + invoiceDate: "2024-12-20T06:22:29+01:00", + paidStatus: "paid", + dueDate: "2024-12-30T08:22:29+01:00", + number: "1", + sentStatus: "sent", + taxIdName: "taxIdName", + canCharge: true, + recipientAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + senderAddress: { + company: "company", + name: "name", + fullAddress: "fullAddress", + }, + items: [ + { + description: "item 1", + quantity: "1", + paid: true, + accountingCode: null, + amount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + }, + ], + payableAmount: "100", + paidAmount: "100", + totalAmount: { + net: "100", + gross: "100", + currency: "EUR", + taxes: [], + }, + invoiceText: "invoiceText", + paidDate: "2024-12-22T06:22:29+01:00", + taxId: null, + chargeAt: null, + customerNumber: null, + notes: null, +}; + +const invoiceResponse: InvoiceApiResponse = { + id: "1", + attributes, + relationships: { + membership: { + data: { + id: "membership-1", + }, + }, + }, +}; + const appTester = createAppTester(App); nock.disableNetConnect(); const trigger = App.triggers[triggerInvoiceCreated.key] as HookTrigger; @@ -40,71 +106,6 @@ describe("triggerInvoiceCreated", () => { const userResponse: UserApiResponse = { included: [{ id: "space-1", attributes: { subdomain: "trial" } }], }; - const attributes: BaseInvoiceProperties = { - invoiceDate: "2024-12-20T06:22:29+01:00", - paidStatus: "paid", - dueDate: "2024-12-30T08:22:29+01:00", - number: "1", - sentStatus: "sent", - taxIdName: "taxIdName", - canCharge: true, - recipientAddress: { - company: "company", - name: "name", - fullAddress: "fullAddress", - }, - senderAddress: { - company: "company", - name: "name", - fullAddress: "fullAddress", - }, - items: [ - { - description: "item 1", - quantity: "1", - paid: true, - accountingCode: null, - amount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - totalAmount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - }, - ], - payableAmount: "100", - paidAmount: "100", - totalAmount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - invoiceText: "invoiceText", - paidDate: "2024-12-22T06:22:29+01:00", - taxId: null, - chargeAt: null, - customerNumber: null, - notes: null, - }; - const invoiceResponse: InvoiceApiResponse = { - id: "1", - attributes, - relationships: { - membership: { - data: { - id: "membership-1", - }, - }, - }, - }; - const scope = nock("https://api.cobot.me"); scope.get("/user?include=adminOf").reply(200, userResponse); scope @@ -126,71 +127,6 @@ describe("triggerInvoiceCreated", () => { it("triggers on new invoice", async () => { const bundle = prepareBundle(); - const attributes: BaseInvoiceProperties = { - invoiceDate: "2024-12-20T06:22:29+01:00", - paidStatus: "paid", - dueDate: "2024-12-30T08:22:29+01:00", - number: "1", - sentStatus: "sent", - taxIdName: "taxIdName", - canCharge: true, - recipientAddress: { - company: "company", - name: "name", - fullAddress: "fullAddress", - }, - senderAddress: { - company: "company", - name: "name", - fullAddress: "fullAddress", - }, - items: [ - { - description: "item 1", - quantity: "1", - paid: true, - accountingCode: null, - amount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - totalAmount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - }, - ], - payableAmount: "100", - paidAmount: "100", - totalAmount: { - net: "100", - gross: "100", - currency: "EUR", - taxes: [], - }, - invoiceText: "invoiceText", - paidDate: "2024-12-22T06:22:29+01:00", - taxId: null, - chargeAt: null, - customerNumber: null, - notes: null, - }; - const invoiceResponse: InvoiceApiResponse = { - id: "1", - attributes, - relationships: { - membership: { - data: { - id: "membership-1", - }, - }, - }, - }; - const scope = nock("https://api.cobot.me"); scope.get("/invoices/12345").reply(200, { data: invoiceResponse }); From c5bce40a5aa7a65798bac98e993b74ac6b97db8d Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Mon, 29 Apr 2024 13:49:42 +0200 Subject: [PATCH 6/8] Added email to invoice trigger --- package.json | 2 +- .../triggers/triggerInvoiceCreated.test.ts | 32 +++++++++++---- src/triggers/triggerInvoiceCreated.ts | 4 +- src/types/api-responses.d.ts | 3 ++ src/utils/api.ts | 40 ++++++++++++++++++- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1abc945..a953262 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cobot-zapier", - "version": "2.2.0", + "version": "2.2.1", "description": "", "main": "index.js", "scripts": { diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts index ae34bdc..e053255 100644 --- a/src/test/triggers/triggerInvoiceCreated.test.ts +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -79,6 +79,11 @@ const invoiceResponse: InvoiceApiResponse = { }, }; +const membershipProfile = { + id: "membership-1", + email: "test@best.com", +}; + const appTester = createAppTester(App); nock.disableNetConnect(); const trigger = App.triggers[triggerInvoiceCreated.key] as HookTrigger; @@ -106,30 +111,40 @@ describe("triggerInvoiceCreated", () => { const userResponse: UserApiResponse = { included: [{ id: "space-1", attributes: { subdomain: "trial" } }], }; - const scope = nock("https://api.cobot.me"); - scope.get("/user?include=adminOf").reply(200, userResponse); - scope + const api2Scope = nock("https://api.cobot.me"); + const api1Scope = nock("https://trial.cobot.me"); + api2Scope.get("/user?include=adminOf").reply(200, userResponse); + api1Scope + .get("/api/memberships/membership-1") + .reply(200, membershipProfile); + api2Scope .get(/\/spaces\/space-1\/invoices/) .reply(200, { data: [invoiceResponse] }); const listRecentEvents = trigger.operation.performList; const results = await appTester(listRecentEvents as any, bundle as any); - + expect(nock.isDone()).toBe(true); expect(results).toStrictEqual([ { ...attributes, id: "1", membershipId: "membership-1", + membership: { + email: "test@best.com", + }, }, ]); }); it("triggers on new invoice", async () => { const bundle = prepareBundle(); - const scope = nock("https://api.cobot.me"); - scope.get("/invoices/12345").reply(200, { data: invoiceResponse }); - + const api1Scope = nock("https://trial.cobot.me"); + const api2Scope = nock("https://api.cobot.me"); + api2Scope.get("/invoices/12345").reply(200, { data: invoiceResponse }); + api1Scope + .get("/api/memberships/membership-1") + .reply(200, membershipProfile); const results = await appTester( triggerInvoiceCreated.operation.perform as any, bundle as any, @@ -141,6 +156,9 @@ describe("triggerInvoiceCreated", () => { { ...attributes, id: "1", + membership: { + email: "test@best.com", + }, membershipId: "membership-1", }, ]); diff --git a/src/triggers/triggerInvoiceCreated.ts b/src/triggers/triggerInvoiceCreated.ts index f157a7c..bacacc3 100644 --- a/src/triggers/triggerInvoiceCreated.ts +++ b/src/triggers/triggerInvoiceCreated.ts @@ -40,7 +40,9 @@ async function parsePayload( bundle: KontentBundle<{}>, ): Promise { const invoiceId = bundle.cleanedRequest.url.split("/").pop(); - const response = await getInvoiceFromApi2(z, invoiceId); + const api1MembershipUrl = + new URL(bundle.cleanedRequest.url).origin + "/api/memberships"; + const response = await getInvoiceFromApi2(z, invoiceId, api1MembershipUrl); if (response) { return [apiResponseToInvoiceOutput(response)]; } else { diff --git a/src/types/api-responses.d.ts b/src/types/api-responses.d.ts index 5d1d8cb..f558752 100644 --- a/src/types/api-responses.d.ts +++ b/src/types/api-responses.d.ts @@ -100,6 +100,9 @@ export type BaseInvoiceProperties = { payableAmount: string; paidAmount: string; totalAmount: Amount; + membership?: { + email: string; + }; }; export type InvoiceApiResponse = { diff --git a/src/utils/api.ts b/src/utils/api.ts index b25e7a0..b9b3c41 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -163,7 +163,40 @@ export const listRecentInvoices = async ( "filter[to]": to, }, }); - return response.data.data; + const invoices = response.data.data as InvoiceApiResponse[]; + const membershipPromises: Promise[] = []; + const api1MembershipUrl = `https://${subdomain}.cobot.me/api/memberships`; + invoices.forEach((invoice) => { + membershipPromises.push( + loadMembershipEmailOnInvoice(z, api1MembershipUrl, invoice), + ); + }); + await Promise.all(membershipPromises); + return invoices; +}; + +const loadMembershipEmailOnInvoice = async ( + z: ZObject, + api1MembershipUrl: string, + invoice: InvoiceApiResponse, +): Promise => { + const membershipId = get(invoice, "relationships.membership.data.id"); + if (!membershipId) { + return invoice; + } + const response = await z.request({ + url: `${api1MembershipUrl}/${membershipId}`, + method: "GET", + headers: { + Accept: "application/vnd.api+json", + }, + }); + const email = response.data.email; + const membership = { + email, + }; + invoice.attributes = { ...invoice.attributes, membership }; + return invoice; }; export const listRecentExternalBookings = async ( @@ -233,6 +266,7 @@ export type ExternalBookingWithResourceApiResponse = export const getInvoiceFromApi2 = async ( z: ZObject, invoiceId: string, + api1MembershipUrl: string, ): Promise => { const response = await z.request({ url: `https://api.cobot.me/invoices/${invoiceId}`, @@ -244,7 +278,9 @@ export const getInvoiceFromApi2 = async ( if (response.status === 404) { return null; } - return response.data.data as InvoiceApiResponse; + const invoice = response.data.data as InvoiceApiResponse; + await loadMembershipEmailOnInvoice(z, api1MembershipUrl, invoice); + return invoice; }; export const getExternalBooking = async ( From 0f21fffba2a23b7d0892c4312480ac48c21bdef1 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Thu, 2 May 2024 18:34:13 +0200 Subject: [PATCH 7/8] Changes based on review --- .../triggers/triggerInvoiceCreated.test.ts | 14 +++----- src/triggers/triggerInvoiceCreated.ts | 14 +++++--- src/types/api-responses.d.ts | 3 -- src/types/outputs.d.ts | 7 +++- src/utils/api-to-output.ts | 24 ++++++++++--- src/utils/api.ts | 36 ++++++------------- src/utils/samples.ts | 5 ++- 7 files changed, 55 insertions(+), 48 deletions(-) diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts index e053255..6247fe2 100644 --- a/src/test/triggers/triggerInvoiceCreated.test.ts +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -79,7 +79,7 @@ const invoiceResponse: InvoiceApiResponse = { }, }; -const membershipProfile = { +const membership = { id: "membership-1", email: "test@best.com", }; @@ -114,9 +114,7 @@ describe("triggerInvoiceCreated", () => { const api2Scope = nock("https://api.cobot.me"); const api1Scope = nock("https://trial.cobot.me"); api2Scope.get("/user?include=adminOf").reply(200, userResponse); - api1Scope - .get("/api/memberships/membership-1") - .reply(200, membershipProfile); + api1Scope.get("/api/memberships/membership-1").reply(200, membership); api2Scope .get(/\/spaces\/space-1\/invoices/) .reply(200, { data: [invoiceResponse] }); @@ -129,8 +127,8 @@ describe("triggerInvoiceCreated", () => { { ...attributes, id: "1", - membershipId: "membership-1", membership: { + membershipId: "membership-1", email: "test@best.com", }, }, @@ -142,9 +140,7 @@ describe("triggerInvoiceCreated", () => { const api1Scope = nock("https://trial.cobot.me"); const api2Scope = nock("https://api.cobot.me"); api2Scope.get("/invoices/12345").reply(200, { data: invoiceResponse }); - api1Scope - .get("/api/memberships/membership-1") - .reply(200, membershipProfile); + api1Scope.get("/api/memberships/membership-1").reply(200, membership); const results = await appTester( triggerInvoiceCreated.operation.perform as any, bundle as any, @@ -157,9 +153,9 @@ describe("triggerInvoiceCreated", () => { ...attributes, id: "1", membership: { + membershipId: "membership-1", email: "test@best.com", }, - membershipId: "membership-1", }, ]); }); diff --git a/src/triggers/triggerInvoiceCreated.ts b/src/triggers/triggerInvoiceCreated.ts index bacacc3..af0afbb 100644 --- a/src/triggers/triggerInvoiceCreated.ts +++ b/src/triggers/triggerInvoiceCreated.ts @@ -40,11 +40,11 @@ async function parsePayload( bundle: KontentBundle<{}>, ): Promise { const invoiceId = bundle.cleanedRequest.url.split("/").pop(); - const api1MembershipUrl = + const api1MembershipsUrl = new URL(bundle.cleanedRequest.url).origin + "/api/memberships"; - const response = await getInvoiceFromApi2(z, invoiceId, api1MembershipUrl); + const response = await getInvoiceFromApi2(z, invoiceId); if (response) { - return [apiResponseToInvoiceOutput(response)]; + return [await apiResponseToInvoiceOutput(z, response, api1MembershipsUrl)]; } else { return []; } @@ -71,7 +71,13 @@ const trigger: HookTrigger = { bundle: KontentBundle, ): Promise => { const invoices = await listRecentInvoices(z, bundle); - return invoices.map((invoice) => apiResponseToInvoiceOutput(invoice)); + const subdomain = bundle.inputData.subdomain; + const api1MembershipsUrl = `https://${subdomain}.cobot.me/api/memberships`; + const invoiceOutputPromises = invoices.map((invoice) => + apiResponseToInvoiceOutput(z, invoice, api1MembershipsUrl), + ); + const invoiceOutputs = await Promise.all(invoiceOutputPromises); + return invoiceOutputs; }, sample: invoiceSample, diff --git a/src/types/api-responses.d.ts b/src/types/api-responses.d.ts index f558752..5d1d8cb 100644 --- a/src/types/api-responses.d.ts +++ b/src/types/api-responses.d.ts @@ -100,9 +100,6 @@ export type BaseInvoiceProperties = { payableAmount: string; paidAmount: string; totalAmount: Amount; - membership?: { - email: string; - }; }; export type InvoiceApiResponse = { diff --git a/src/types/outputs.d.ts b/src/types/outputs.d.ts index 53d4881..e0e8541 100644 --- a/src/types/outputs.d.ts +++ b/src/types/outputs.d.ts @@ -58,7 +58,12 @@ export type MembershipOutput = { payment_method_name: string | null; }; +export type InvoiceMembershipOutput = { + membershipId: string; + email: string | null; +}; + export type InvoiceOutput = BaseInvoiceProperties & { - membershipId?: string; id: string; + membership?: InvoiceMembershipOutput; }; diff --git a/src/utils/api-to-output.ts b/src/utils/api-to-output.ts index 2c8738d..a54340b 100644 --- a/src/utils/api-to-output.ts +++ b/src/utils/api-to-output.ts @@ -11,7 +11,12 @@ import { MembershipOutput, InvoiceOutput, } from "../types/outputs"; -import { ExternalBookingWithResourceApiResponse } from "./api"; +import { ZObject } from "zapier-platform-core"; +import { get } from "lodash"; +import { + ExternalBookingWithResourceApiResponse, + loadMembershipEmailOnInvoice, +} from "./api"; export function apiResponseToMembershipOutput( membership: MembershipApiResponse, @@ -27,14 +32,25 @@ export function apiResponseToMembershipOutput( }; } -export function apiResponseToInvoiceOutput( +export async function apiResponseToInvoiceOutput( + z: ZObject, invoice: InvoiceApiResponse, -): InvoiceOutput { + api1MembershipsUrl: string, +): Promise { const attributes = invoice.attributes; + const membershipId = get(invoice, "relationships.membership.data.id"); + if (!membershipId) { + return { + ...attributes, + id: invoice.id, + }; + } + const url = `${api1MembershipsUrl}/${membershipId}`; + const membership = await loadMembershipEmailOnInvoice(z, url, membershipId); return { ...attributes, id: invoice.id, - membershipId: invoice.relationships?.membership?.data?.id ?? undefined, + membership, }; } diff --git a/src/utils/api.ts b/src/utils/api.ts index b9b3c41..c61f557 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -16,6 +16,7 @@ import { UserApiResponse, InvoiceApiResponse, } from "../types/api-responses"; +import { InvoiceMembershipOutput } from "../types/outputs"; type Space = { id: string; @@ -163,40 +164,26 @@ export const listRecentInvoices = async ( "filter[to]": to, }, }); - const invoices = response.data.data as InvoiceApiResponse[]; - const membershipPromises: Promise[] = []; - const api1MembershipUrl = `https://${subdomain}.cobot.me/api/memberships`; - invoices.forEach((invoice) => { - membershipPromises.push( - loadMembershipEmailOnInvoice(z, api1MembershipUrl, invoice), - ); - }); - await Promise.all(membershipPromises); - return invoices; + return response.data.data; }; -const loadMembershipEmailOnInvoice = async ( +export const loadMembershipEmailOnInvoice = async ( z: ZObject, - api1MembershipUrl: string, - invoice: InvoiceApiResponse, -): Promise => { - const membershipId = get(invoice, "relationships.membership.data.id"); - if (!membershipId) { - return invoice; - } + membershipUrl: string, + membershipId: string, +): Promise => { const response = await z.request({ - url: `${api1MembershipUrl}/${membershipId}`, + url: membershipUrl, method: "GET", headers: { Accept: "application/vnd.api+json", }, }); const email = response.data.email; - const membership = { + return { email, + membershipId, }; - invoice.attributes = { ...invoice.attributes, membership }; - return invoice; }; export const listRecentExternalBookings = async ( @@ -266,7 +253,6 @@ export type ExternalBookingWithResourceApiResponse = export const getInvoiceFromApi2 = async ( z: ZObject, invoiceId: string, - api1MembershipUrl: string, ): Promise => { const response = await z.request({ url: `https://api.cobot.me/invoices/${invoiceId}`, @@ -278,9 +264,7 @@ export const getInvoiceFromApi2 = async ( if (response.status === 404) { return null; } - const invoice = response.data.data as InvoiceApiResponse; - await loadMembershipEmailOnInvoice(z, api1MembershipUrl, invoice); - return invoice; + return response.data.data; }; export const getExternalBooking = async ( diff --git a/src/utils/samples.ts b/src/utils/samples.ts index f81b6ea..de0f2b8 100644 --- a/src/utils/samples.ts +++ b/src/utils/samples.ts @@ -74,7 +74,10 @@ export const invoiceSample: InvoiceOutput = { taxId: "DE12345", taxIdName: "UID", customerNumber: "100", - membershipId: "c9a99a71ac8df98d29de357180d273d3", + membership: { + membershipId: "14c12f62ac8df98d29de357180d673e1", + email: "joe@doe.com", + }, recipientAddress: { name: "Jane Smith", company: "Acme Inc.", From f44162bc7e3f70dadf26d6dd1afba7f6a9d70087 Mon Sep 17 00:00:00 2001 From: Jsnxyz Date: Mon, 6 May 2024 15:24:58 +0200 Subject: [PATCH 8/8] refactored based on review --- .../triggers/triggerInvoiceCreated.test.ts | 4 ++-- src/types/outputs.d.ts | 2 +- src/utils/api-to-output.ts | 12 ++++++------ src/utils/api.ts | 19 ------------------- src/utils/samples.ts | 2 +- 5 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/test/triggers/triggerInvoiceCreated.test.ts b/src/test/triggers/triggerInvoiceCreated.test.ts index 6247fe2..929a30d 100644 --- a/src/test/triggers/triggerInvoiceCreated.test.ts +++ b/src/test/triggers/triggerInvoiceCreated.test.ts @@ -128,7 +128,7 @@ describe("triggerInvoiceCreated", () => { ...attributes, id: "1", membership: { - membershipId: "membership-1", + id: "membership-1", email: "test@best.com", }, }, @@ -153,7 +153,7 @@ describe("triggerInvoiceCreated", () => { ...attributes, id: "1", membership: { - membershipId: "membership-1", + id: "membership-1", email: "test@best.com", }, }, diff --git a/src/types/outputs.d.ts b/src/types/outputs.d.ts index e0e8541..b360184 100644 --- a/src/types/outputs.d.ts +++ b/src/types/outputs.d.ts @@ -59,7 +59,7 @@ export type MembershipOutput = { }; export type InvoiceMembershipOutput = { - membershipId: string; + id: string; email: string | null; }; diff --git a/src/utils/api-to-output.ts b/src/utils/api-to-output.ts index a54340b..7c34fdd 100644 --- a/src/utils/api-to-output.ts +++ b/src/utils/api-to-output.ts @@ -13,10 +13,7 @@ import { } from "../types/outputs"; import { ZObject } from "zapier-platform-core"; import { get } from "lodash"; -import { - ExternalBookingWithResourceApiResponse, - loadMembershipEmailOnInvoice, -} from "./api"; +import { ExternalBookingWithResourceApiResponse, apiCallUrl } from "./api"; export function apiResponseToMembershipOutput( membership: MembershipApiResponse, @@ -46,11 +43,14 @@ export async function apiResponseToInvoiceOutput( }; } const url = `${api1MembershipsUrl}/${membershipId}`; - const membership = await loadMembershipEmailOnInvoice(z, url, membershipId); + const membership: MembershipApiResponse = await apiCallUrl(z, url); return { ...attributes, id: invoice.id, - membership, + membership: { + id: membershipId, + email: membership.email, + }, }; } diff --git a/src/utils/api.ts b/src/utils/api.ts index c61f557..6c12f19 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -167,25 +167,6 @@ export const listRecentInvoices = async ( return response.data.data; }; -export const loadMembershipEmailOnInvoice = async ( - z: ZObject, - membershipUrl: string, - membershipId: string, -): Promise => { - const response = await z.request({ - url: membershipUrl, - method: "GET", - headers: { - Accept: "application/vnd.api+json", - }, - }); - const email = response.data.email; - return { - email, - membershipId, - }; -}; - export const listRecentExternalBookings = async ( z: ZObject, bundle: KontentBundle, diff --git a/src/utils/samples.ts b/src/utils/samples.ts index de0f2b8..8bd4598 100644 --- a/src/utils/samples.ts +++ b/src/utils/samples.ts @@ -75,7 +75,7 @@ export const invoiceSample: InvoiceOutput = { taxIdName: "UID", customerNumber: "100", membership: { - membershipId: "14c12f62ac8df98d29de357180d673e1", + id: "14c12f62ac8df98d29de357180d673e1", email: "joe@doe.com", }, recipientAddress: {