Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import expensify from "../../app/expensify.app";

export default defineAction({
key: "expensify-create-expense",
version: "0.0.3",
version: "0.0.4",
name: "Create Expense",
description: "Creates a new expense. [See docs here](https://integrations.expensify.com/Integration-Server/doc/#expense-creator)",
type: "action",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import utils from "../../common/utils";

export default defineAction({
key: "expensify-create-report",
version: "0.0.1",
version: "0.0.2",
name: "Create Report",
description: "Creates a new report with transactions in a user's account. [See docs here](https://integrations.expensify.com/Integration-Server/doc/#report-creator)",
type: "action",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import fs from "fs";

export default defineAction({
key: "expensify-export-report-to-pdf",
version: "0.0.3",
version: "0.0.4",
name: "Export Report To PDF",
description: "Export a report to PDF. [See docs here](https://integrations.expensify.com/Integration-Server/doc/#report-exporter)",
type: "action",
Expand Down
238 changes: 238 additions & 0 deletions components/expensify/actions/export-report/export-report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import { defineAction } from "@pipedream/types";
import expensify from "../../app/expensify.app";
import fs from "fs";
import {
axios, ConfigurationError,
} from "@pipedream/platform";
import qs from "qs";

export default defineAction({
key: "expensify-export-report",
name: "Export Report",
description: "Export a report to a PDF file. [See the documentation](https://integrations.expensify.com/Integration-Server/doc/#report-exporter)",
version: "0.0.1",
type: "action",
props: {
expensify,
reportIds: {
type: "string[]",
label: "Report IDs",
description: "The IDs of the reports to be exported. Required if `startDate` or a`pprovedAfter` are not specified.",
optional: true,
},
startDate: {
type: "string",
label: "Start Date",
description: "The start date of the report. Format: YYYY-MM-DD. Required if `reportIds` or `approvedAfter ` are not specified.",
optional: true,
},
endDate: {
type: "string",
label: "End Date",
description: "The end date of the report. Format: YYYY-MM-DD. Conditionally required, if either `startDate` or `approvedAfter` is more than one year ago.",
optional: true,
},
approvedAfter: {
type: "string",
label: "Approved After",
description: "Filters out all reports approved before the given date, whichever occurred last (inclusive). Required if `reportIds` or `startDate` are not specified",
optional: true,
},
fileExtension: {
type: "string",
label: "File Extension",
description: "Specifies the format of the generated report",
options: [
"csv",
"xls",
"xlsx",
"txt",
"pdf",
"json",
"xml",
],
},
markAsExportedFilter: {
type: "boolean",
label: "Mark as Exported (Filter)",
description: "Filters out reports that have already been exported with that label out",
optional: true,
},
reportStates: {
type: "string[]",
label: "Report States",
description: "Only the reports matching the specified status(es) will be exported",
options: [
"OPEN",
"SUBMITTED",
"APPROVED",
"REIMBURSED",
"ARCHIVED",
],
optional: true,
},
employeeEmail: {
type: "string",
label: "Employee Email",
description: "The reports will be exported from that the specified employee email",
optional: true,
},
policyIds: {
propDefinition: [
expensify,
"policyExportIds",
],
},
fileBaseName: {
type: "string",
label: "File Base Name",
description: "The base name of the file to be exported",
optional: true,
},
includeFullPageReceiptsPdf: {
type: "boolean",
label: "Include Full Page Receipts PDF",
description: "Specifies whether generated PDFs should include full page receipts. This parameter is used only if fileExtension contains pdf.",
optional: true,
},
emailRecipients: {
type: "string[]",
label: "Email Recipients",
description: "People to email at the end of the export",
optional: true,
},
markAsExported: {
type: "string",
label: "Mark as Exported",
description: "Mark the reports as exported with the given label",
optional: true,
},
templatePath: {
type: "string",
label: "Template Path",
description: "The path in the /tmp directory to the template to use for the export",
optional: true,
},
limit: {
type: "string",
label: "Limit",
description: "Maximum number of reports to export",
optional: true,
},
test: {
type: "boolean",
label: "Test Mode",
description: "If set to true, actions defined in `onFinish` (i.e. email, markAsExported) will not be executed",
optional: true,
},
syncDir: {
type: "dir",
accessMode: "write",
sync: true,
},
},
async run({ $ }) {
if (!this.reportIds && !this.startDate && !this.approvedAfter) {
throw new ConfigurationError("At least one of `reportIds`, `startDate`, or `approvedAfter` must be specified");
}

const onFinish = [];
if (this.emailRecipients) {
onFinish.push({
actionName: "email",
recipients: this.emailRecipients.join(","),
});
}

if (this.markAsExported) {
onFinish.push({
actionName: "markAsExported",
label: this.markAsExported,
});
}

const data = {
type: "file",
credentials: {
partnerUserID: this.expensify._partnerUserId(),
partnerUserSecret: this.expensify._partnerUserSecret(),
},
onReceive: {
immediateResponse: [
"returnRandomFileName",
],
},
inputSettings: {
type: "combinedReportData",
filters: {
reportIDList: this.reportIds
? this.reportIds.join(",")
: undefined,
startDate: this.startDate,
endDate: this.endDate,
approvedAfter: this.approvedAfter,
markAsExported: this.markAsExportedFilter,
policyIDList: this.policyIds
? this.policyIds.join(",")
: undefined,
},
reportStates: this.reportStates
? this.reportStates.join(",")
: undefined,
employeeEmail: this.employeeEmail,
limit: this.limit,
},
outputSettings: {
fileExtension: this.fileExtension,
fileBaseName: this.fileBaseName,
includeFullPageReceiptsPdf: this.includeFullPageReceiptsPdf,
},
onFinish,
test: this.test,
};

let fileName;
const args = {
method: "post",
url: `${this.expensify._apiUrl()}`,
};

if (!this.templatePath) {
fileName = await axios($, {
...args,
data: qs.stringify({
requestJobDescription: JSON.stringify(data),
template: "default",
}),
});
} else {
fileName = await axios($, {
...args,
data: qs.stringify({
requestJobDescription: JSON.stringify(data),
template: fs.readFileSync(this.templatePath.includes("tmp/")
? this.templatePath
: `/tmp/${this.templatePath}`, "utf8"),
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
}

const fileBuffer = await this.expensify.downloadFile({
$,
fileName,
});

const path = `/tmp/${fileName}`;

await fs.writeFileSync(path, fileBuffer);

if (fileBuffer) {
$.export("$summary", `Successfully exported report in ${path}`);
}

return path;
},
});
31 changes: 28 additions & 3 deletions components/expensify/app/expensify.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,30 @@ export default defineApp({
type: "app",
app: "expensify",
propDefinitions: {
policyExportIds: {
type: "string[]",
label: "Policy IDs",
description: "The IDs of the policies to export",
optional: true,
async options() {
const { policyList } = await this.listPolicies();
return policyList?.map(({
id, name,
}) => ({
label: name,
value: id,
})) || [];
},
},
employeeEmail: {
type: "string",
label: "Employee Email",
description: "The expenses will be created in this account.",
description: "The expenses will be created in this account",
},
policyId: {
type: "string",
label: "Policy ID",
description: "Select the policy where the report will be created.",
description: "Select the policy where the report will be created",
async options({ userEmail }) {
const { policyList } = await this.getPolicyList({
userEmail,
Expand Down Expand Up @@ -152,7 +167,17 @@ export default defineApp({
},
}, $);
},

async listPolicies({ $ = this } = {}) {
return this._makeRequest({
method: "post",
data: {
type: "get",
inputSettings: {
type: "policyList",
},
},
}, $);
},
async downloadFile({
$, fileName,
}) {
Expand Down
2 changes: 1 addition & 1 deletion components/expensify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/expensify",
"version": "0.1.0",
"version": "0.2.0",
"description": "Pipedream Expensify Components",
"main": "dist/app/expensify.app.mjs",
"keywords": [
Expand Down
Loading