Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ PLAID_ENV=sandbox
# If you don't see the institution you want in Link, remove any products you aren't using.
# Important: When moving to Production, make sure to update this list with only the products
# you plan to use. Otherwise, you may be billed for unneeded products.
# NOTE: Income_verification has to be used seperately from all other products due to the specific
# flow.
PLAID_PRODUCTS=auth,transactions
# PLAID_COUNTRY_CODES is a comma-separated list of countries to use when
# initializing Link, e.g. PLAID_COUNTRY_CODES=US,CA.
Expand Down
39 changes: 37 additions & 2 deletions frontend/src/Components/ProductTypes/Products.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ import {
identityCategories,
balanceCategories,
investmentsCategories,
investmentsTransactionsCategories,
liabilitiesCategories,
paymentCategories,
assetsCategories,
incomePaystubsCategories,
transferCategories,
transformAuthData,
transformTransactionsData,
transformBalanceData,
transformInvestmentsData,
transformInvestmentTransactionsData,
transformLiabilitiesData,
transformIdentityData,
transformPaymentData,
transformAssetsData,
transformTransferData,
transformIncomePaystubsData,
} from "../../dataUtilities";

const Products = () => {
Expand Down Expand Up @@ -81,6 +87,7 @@ const Products = () => {
transformData={transformBalanceData}
/>
{products.includes("investments") && (
<>
<Endpoint
endpoint="holdings"
name="Investments"
Expand All @@ -89,8 +96,26 @@ const Products = () => {
description="Retrieve investment holdings on file with the bank,
brokerage, or investment institution. Analyze over-exposure
to market segments."
transformData={transformInvestmentsData}
/>
transformData={transformInvestmentsData}
/>
<Endpoint
endpoint="investments_transactions"
name="Investments Transactions"
categories={investmentsTransactionsCategories}
schema="/investments/transactions/get"
description="Retrieve investment transactions on file with the bank,
brokerage, or investments institution."
transformData={transformInvestmentTransactionsData}
/>
<Endpoint
endpoint="liabilities"
name="Liabilities"
categories={liabilitiesCategories}
schema="/liabilities/get"
description="Retrieve liabilities and various details about an Item with loan or credit accounts."
transformData={transformLiabilitiesData}
/>
</>
)}
{products.includes("transfer") && (
<Endpoint
Expand All @@ -102,6 +127,16 @@ const Products = () => {
transformData={transformTransferData}
/>
)}
{products.includes("income_verification") && (
<Endpoint
endpoint="/income/verification/paystubs"
name="Income Paystubs"
categories={incomePaystubsCategories}
schema="/income/verification/paystubs"
description="(Deprecated) Retrieve information from the paystubs used for income verification"
transformData={transformIncomePaystubsData}
/>
)}
</ProductTypesContainer>
);
};
Expand Down
112 changes: 106 additions & 6 deletions frontend/src/dataUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
TransactionsGetResponse,
IdentityGetResponse,
InvestmentsHoldingsGetResponse,
InvestmentsTransactionsGetResponse,
AccountsGetResponse,
ItemGetResponse,
InstitutionsGetByIdResponse,
Expand All @@ -11,6 +12,9 @@ import {
AssetReportGetResponse,
AssetReport,
TransferGetResponse,
IncomeVerificationPaystubsGetResponse,
Paystub,
Earnings,
} from "plaid/dist/api";

const formatCurrency = (
Expand Down Expand Up @@ -63,6 +67,12 @@ interface InvestmentsDataItem {
name: string;
}

interface InvestmentsTransactionItem {
amount: number;
date: string;
name: string;
}

interface LiabilitiessDataItem {
amount: string;
date: string;
Expand Down Expand Up @@ -98,6 +108,12 @@ interface TransferDataItem {
network: string;
}

interface IncomePaystubsDataItem {
description: string;
currentAmount: number | null;
currency: number | null;
}

export interface ErrorDataItem {
error_type: string;
error_code: string;
Expand All @@ -113,11 +129,13 @@ export type DataItem =
| IdentityDataItem
| BalanceDataItem
| InvestmentsDataItem
| InvestmentsTransactionItem
| LiabilitiessDataItem
| ItemDataItem
| PaymentDataItem
| AssetsDataItem
| TransferDataItem;
| TransferDataItem
| IncomePaystubsDataItem;

export type Data = Array<DataItem>;

Expand Down Expand Up @@ -216,6 +234,21 @@ export const investmentsCategories: Array<Categories> = [
},
];

export const investmentsTransactionsCategories: Array<Categories> = [
{
title: "Name",
field: "name",
},
{
title: "Amount",
field: "amount",
},
{
title: "Date",
field: "date",
},
];

export const liabilitiesCategories: Array<Categories> = [
{
title: "Name",
Expand Down Expand Up @@ -338,6 +371,21 @@ export const transferCategories: Array<Categories> = [
},
];

export const incomePaystubsCategories: Array<Categories> = [
{
title: "Description",
field: "description",
},
{
title: "Current Amount",
field: "currentAmount",
},
{
title: "Currency",
field: "currency",
}
]

export const transformAuthData = (data: AuthGetResponse) => {
return data.numbers.ach!.map((achNumbers) => {
const account = data.accounts!.filter((a) => {
Expand Down Expand Up @@ -458,10 +506,41 @@ export const transformInvestmentsData = (data: InvestmentData) => {
});
};

export const transformLiabilitiesData = (data: LiabilitiesGetResponse) => {
const liabilitiesData = data.liabilities;
interface InvestmentsTransactionData {
error: null;
investments_transactions: InvestmentsTransactionsGetResponse;
}

export const transformInvestmentTransactionsData = (data: InvestmentsTransactionData) => {
const investmentTransactionsData = data.investments_transactions.investment_transactions!.sort(function (a,b) {
if (a.account_id > b.account_id) return 1;
return -1;
});
return investmentTransactionsData.map((investmentTransaction) => {
const security = data.investments_transactions.securities!.filter(
(sec) => sec.security_id === investmentTransaction.security_id
)[0];

const obj: DataItem = {
name: security.name!,
amount: investmentTransaction.amount,
date: investmentTransaction.date,
};
return obj;
});
};

interface LiabilitiesDataResponse {
error: null;
liabilities: LiabilitiesGetResponse;
}

export const transformLiabilitiesData = (data: LiabilitiesDataResponse) => {
const liabilitiesData = data.liabilities.liabilities;
//console.log(liabilitiesData)
//console.log("random")
const credit = liabilitiesData.credit!.map((credit) => {
const account = data.accounts.filter(
const account = data.liabilities.accounts.filter(
(acc) => acc.account_id === credit.account_id
)[0];
const obj: DataItem = {
Expand All @@ -477,7 +556,7 @@ export const transformLiabilitiesData = (data: LiabilitiesGetResponse) => {
});

const mortgages = liabilitiesData.mortgage?.map((mortgage) => {
const account = data.accounts.filter(
const account = data.liabilities.accounts.filter(
(acc) => acc.account_id === mortgage.account_id
)[0];
const obj: DataItem = {
Expand All @@ -493,7 +572,7 @@ export const transformLiabilitiesData = (data: LiabilitiesGetResponse) => {
});

const student = liabilitiesData.student?.map((student) => {
const account = data.accounts.filter(
const account = data.liabilities.accounts.filter(
(acc) => acc.account_id === student.account_id
)[0];
const obj: DataItem = {
Expand Down Expand Up @@ -598,3 +677,24 @@ export const transformAssetsData = (data: AssetResponseData) => {
});
});
};

interface IncomePaystub {
paystubs: IncomeVerificationPaystubsGetResponse,
}

export const transformIncomePaystubsData = (data: IncomePaystub) => {
const paystubsItemsArray: Array<Paystub> = data.paystubs.paystubs
var finalArray: Array<IncomePaystubsDataItem> = []
for (var i = 0; i < paystubsItemsArray.length; i++){
var ActualEarningVariable: any = paystubsItemsArray[i].earnings
for (var j = 0; j < ActualEarningVariable.breakdown.length; j++){
var payStubItem: IncomePaystubsDataItem = {
description: paystubsItemsArray[i].employer.name + '_' + ActualEarningVariable.breakdown[j].description,
currentAmount: ActualEarningVariable.breakdown[j].current_amount,
currency: ActualEarningVariable.breakdown[j].iso_currency_code
}
finalArray.push(payStubItem)
}
}
return finalArray
}
4 changes: 2 additions & 2 deletions go/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func main() {
r.GET("/api/payment", payment)
r.GET("/api/create_public_token", createPublicToken)
r.POST("/api/create_link_token", createLinkToken)
r.GET("/api/investment_transactions", investmentTransactions)
r.GET("/api/investments_transactions", investmentTransactions)
r.GET("/api/holdings", holdings)
r.GET("/api/assets", assets)
r.GET("/api/transfer", transfer)
Expand Down Expand Up @@ -395,7 +395,7 @@ func investmentTransactions(c *gin.Context) {
}

c.JSON(http.StatusOK, gin.H{
"investment_transactions": invTxResp,
"investments_transactions": invTxResp,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import retrofit2.Response;

@Path("/investment_transactions")
@Path("/investments_transactions")
@Produces(MediaType.APPLICATION_JSON)
public class InvestmentTransactionsResource {
private final PlaidApi plaidClient;
Expand Down Expand Up @@ -48,10 +48,10 @@ public InvestmentTransactionsResponse getAccounts() throws IOException {

private static class InvestmentTransactionsResponse {
@JsonProperty
private InvestmentsTransactionsGetResponse investmentTransactions;
private InvestmentsTransactionsGetResponse investmentsTransactions;

public InvestmentTransactionsResponse(InvestmentsTransactionsGetResponse investmentTransactions) {
this.investmentTransactions = investmentTransactions;
this.investmentsTransactions = investmentTransactions;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import java.util.List;
import java.util.Date;
import java.util.ArrayList;
import java.util.Arrays;

import javax.ws.rs.POST;
Expand All @@ -29,13 +30,15 @@ public class LinkTokenResource {
private final List<String> plaidProducts;
private final List<String> countryCodes;
private final String redirectUri;
private final List<Products> correctedPlaidProducts;

public LinkTokenResource(PlaidApi plaidClient, List<String> plaidProducts,
List<String> countryCodes, String redirectUri) {
this.plaidClient = plaidClient;
this.plaidProducts = plaidProducts;
this.countryCodes = countryCodes;
this.redirectUri = redirectUri;
this.correctedPlaidProducts = new ArrayList<>();
}

public static class LinkToken {
Expand All @@ -55,10 +58,14 @@ public LinkToken(String linkToken) {
LinkTokenCreateRequestUser user = new LinkTokenCreateRequestUser()
.clientUserId(clientUserId);

for (int i = 0; i < this.plaidProducts.size(); i++){
this.correctedPlaidProducts.add(Products.fromValue(this.plaidProducts.get(i)));
};

LinkTokenCreateRequest request = new LinkTokenCreateRequest()
.user(user)
.clientName("Quickstart Client")
.products(Arrays.asList(Products.AUTH, Products.TRANSACTIONS))
.products(this.correctedPlaidProducts)
.countryCodes(Arrays.asList(CountryCode.US, CountryCode.CA))
.language("en")
.redirectUri(this.redirectUri);
Expand Down
Loading