Skip to content

Commit

Permalink
feat: add support for attaching multiple receipts (files) to a claim
Browse files Browse the repository at this point in the history
Fixes #8.
  • Loading branch information
timrogers committed Aug 1, 2023
1 parent e0ff9e6 commit 26356e2
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 23 deletions.
10 changes: 7 additions & 3 deletions src/claims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface Claim {
merchant: string;
purchaseDate: string;
description: string;
receiptPath: string;
receiptPath: string[];
}

const PURCHASE_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
Expand Down Expand Up @@ -42,8 +42,12 @@ export const claimParamsToCreateClaimOptions = async (
if (!isValidPurchaseDate(claim.purchaseDate))
throw new Error('Purchase date must be in YYYY-MM-DD format.');
if (!isValidAmount(claim.amount)) throw new Error('Amount must be in the format 0.00.');
if (!existsSync(claim.receiptPath))
throw new Error(`Receipt path '${claim.receiptPath}' does not exist.`);

for (const path of claim.receiptPath) {
if (!existsSync(path)) {
throw new Error(`Receipt path '${path}' does not exist.`);
}
}

return {
...claim,
Expand Down
6 changes: 3 additions & 3 deletions src/commands/submit-claim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface Arguments {
category?: string;
purchaseDate: string;
description: string;
receiptPath: string;
receiptPath: string[];
openaiApiKey?: string;
}

Expand Down Expand Up @@ -133,8 +133,8 @@ command
)
.requiredOption('--description <description>', 'The description of the claim')
.requiredOption(
'--receipt-path <receipt-path>',
'The path of the receipt. JPEG, PNG, PDF and HEIC files up to 10MB are accepted.',
'--receipt-path <receipt-path...>',
'The path of the receipt. JPEG, PNG, PDF and HEIC files up to 10MB are accepted. You may specify this argument multiple times to attach multiple receipts.',
)
.option('--access-token <access_token>', 'Access token used to authenticate with Forma')
.option(
Expand Down
7 changes: 5 additions & 2 deletions src/commands/submit-claims-from-csv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ const readClaimsFromCsv = async (inputPath: string): Promise<Claim[]> => {
);
}

claims.push(row as Claim);
const receiptPath = row.receiptPath.split(',').map((path) => path.trim());
const claim: Claim = { ...row, receiptPath };

claims.push(claim);
})
.on('end', () => {
resolve(claims);
Expand All @@ -59,7 +62,7 @@ command
.name('submit-claims-from-csv')
.version(VERSION)
.description(
'Submit multiple Forms claims from a CSV. To generate a template CSV to fill in, use the `generate-template-csv` command.',
'Submit multiple Forms claims from a CSV. To generate a template CSV to fill in, use the `generate-template-csv` command. You may attach multiple receipts to a claim by filling the `receipt_path` column with comma-separated paths.',
)
.requiredOption('--input-path <input_path>', 'The path to the CSV to read claims from')
.option('--access-token <access_token>', 'Access token used to authenticate with Forma')
Expand Down
32 changes: 17 additions & 15 deletions src/forma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface CreateClaimOptions {
merchant: string;
purchaseDate: string;
description: string;
receiptPath: string;
receiptPath: string[];
accessToken: string;
benefitId: string;
categoryId: string;
Expand Down Expand Up @@ -187,22 +187,24 @@ export const createClaim = async (opts: CreateClaimOptions): Promise<void> => {
subcategoryValue,
} = opts;

const data = {
type: 'transaction',
is_recurring: 'false',
amount,
transaction_date: purchaseDate,
default_employee_wallet_id: benefitId,
note: description,
category: categoryId,
category_alias: '',
subcategory: subcategoryValue,
subcategory_alias: subcategoryAlias ?? '',
reimbursement_vendor: merchant,
file: receiptPath.map((path) => createReadStream(path)),
};

const response = await axios.post(
'https://api.joinforma.com/client/api/v2/claims?is_mobile=true',
{
type: 'transaction',
is_recurring: 'false',
amount,
transaction_date: purchaseDate,
default_employee_wallet_id: benefitId,
note: description,
category: categoryId,
category_alias: '',
subcategory: subcategoryValue,
subcategory_alias: subcategoryAlias ?? '',
reimbursement_vendor: merchant,
file: [createReadStream(receiptPath)],
},
data,
{
headers: {
'Content-Type': 'multipart/form-data',
Expand Down

0 comments on commit 26356e2

Please sign in to comment.