Skip to content

Commit

Permalink
4. Summary page
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-bizz committed Oct 10, 2024
1 parent 4e73a5f commit 90c7871
Show file tree
Hide file tree
Showing 10 changed files with 900 additions and 8 deletions.
6 changes: 6 additions & 0 deletions pages/api/Schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import { EntryHistoriesResolvers } from './reports/entryHistories/resolvers';
import ExpectedMonthlyTotalReportTypeDefs from './reports/expectedMonthlyTotal/expectedMonthlyTotal.graphql';
import { ExpectedMonthlyTotalReportResolvers } from './reports/expectedMonthlyTotal/resolvers';
import FinancialAccountsTypeDefs from './reports/financialAccounts/financialAccounts.graphql';
import FinancialAccountSummaryTypeDefs from './reports/financialAccounts/financialAccounts/financialAccounts.graphql';
import { FinancialAccountSummaryResolvers } from './reports/financialAccounts/financialAccounts/resolvers';
import { FinancialAccountsResolvers } from './reports/financialAccounts/resolvers';
import FourteenMonthReportTypeDefs from './reports/fourteenMonth/fourteenMonth.graphql';
import { FourteenMonthReportResolvers } from './reports/fourteenMonth/resolvers';
Expand Down Expand Up @@ -127,6 +129,10 @@ const schema = buildSubgraphSchema([
typeDefs: DeleteTagsTypeDefs,
resolvers: DeleteTagsResolvers,
},
{
typeDefs: FinancialAccountSummaryTypeDefs,
resolvers: FinancialAccountSummaryResolvers,
},
...integrationSchema,
...organizationSchema,
...preferencesSchema,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { fetchAllData } from 'src/lib/deserializeJsonApi';
import { FinancialAccountSummaryResponse } from '../../../../graphql-rest.page.generated';

export interface FinancialAccountSummaryRest {
id: string;
attributes: {
closing_balance: number;
credits: number;
debits: number;
difference: number;
end_date: string;
opening_balance: number;
start_date: string;
};
relationships: {
credit_by_categories: { data: IdType[] };
debit_by_categories: { data: IdType[] };
};
}

interface IdType {
id: string;
type: string;
}

export const financialAccountSummaryHandler = ({
data,
included,
}: {
data: FinancialAccountSummaryRest[];
included: unknown[];
}): FinancialAccountSummaryResponse[] => {
const financialAccountSummary = data.map((item) => {
return fetchAllData(item, included);
}) as FinancialAccountSummaryResponse[];

return financialAccountSummary;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extend type Query {
financialAccountSummary(
input: FinancialAccountSummaryInput!
): [FinancialAccountSummaryResponse]!
}

input FinancialAccountSummaryInput {
accountListId: ID!
financialAccountId: ID!
}

type FinancialAccountSummaryResponse {
id: ID!
closingBalance: String
credits: String
debits: String
difference: String
endDate: String!
openingBalance: String
startDate: String!
creditByCategories: [FinancialAccountSummaryCategory]!
debitByCategories: [FinancialAccountSummaryCategory]!
}

type FinancialAccountSummaryCategory {
id: ID!
amount: String
category: FinancialAccountCategory
}

type FinancialAccountCategory {
id: ID!
code: String
name: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Resolvers } from '../../../../graphql-rest.page.generated';

export const FinancialAccountSummaryResolvers: Resolvers = {
Query: {
financialAccountSummary: (
_source,
{ input: { accountListId, financialAccountId } },
{ dataSources },
) => {
return dataSources.mpdxRestApi.financialAccountSummary(
accountListId,
financialAccountId,
);
},
},
};
34 changes: 30 additions & 4 deletions pages/api/graphql-rest.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import {
FinancialAccountResponse,
setActiveFinancialAccount,
} from './Schema/reports/financialAccounts/datahandler';
import { financialAccountSummaryHandler } from './Schema/reports/financialAccounts/financialAccounts/datahandler';
import {
FourteenMonthReportResponse,
mapFourteenMonthReport,
Expand Down Expand Up @@ -758,11 +759,26 @@ class MpdxRestApi extends RESTDataSource {
return setActiveFinancialAccount(data);
}

async deleteComment(taskId: string, commentId: string) {
const { data }: { data: DeleteCommentResponse } = await this.delete(
`tasks/${taskId}/comments/${commentId}`,
//
// Financial Account Report -- Start

async financialAccountSummary(
accountListId: string,
financialAccountId: string,
) {
const include =
'credit_by_categories,debit_by_categories,credit_by_categories.category,debit_by_categories.category';
const filters = `filter[account_list_id]=${accountListId}&filter[financial_account_id]=${financialAccountId}`;
const fields =
'fields[financial_account_entry_by_categories]=amount,category&fields[financial_account_entry_categories]=name,code' +
'&fields[reports_entry_histories_periods]=closing_balance,opening_balance,start_date,end_date,credits,debits,difference,credit_by_categories,debit_by_categories';

const data = await this.get(
`reports/entry_histories?${fields}&${filters}&include=${include}`,
);
return DeleteComment({ ...data, id: commentId });

return financialAccountSummaryHandler(data);
}
}

async getEntryHistories(
Expand All @@ -782,6 +798,16 @@ class MpdxRestApi extends RESTDataSource {
});
}

//
// Financial Account Report -- End

async deleteComment(taskId: string, commentId: string) {
const { data }: { data: DeleteCommentResponse } = await this.delete(
`tasks/${taskId}/comments/${commentId}`,
);
return DeleteComment({ ...data, id: commentId });
}

async updateComment(taskId: string, commentId: string, body: string) {
const { data }: { data: UpdateCommentResponse } = await this.put(
`tasks/${taskId}/comments/${commentId}`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import React from 'react';
import { ThemeProvider } from '@mui/material/styles';
import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { render } from '@testing-library/react';
import { SnackbarProvider } from 'notistack';
import { I18nextProvider } from 'react-i18next';
import TestRouter from '__tests__/util/TestRouter';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { FinancialAccountsWrapper } from 'pages/accountLists/[accountListId]/reports/financialAccounts/Wrapper';
import i18n from 'src/lib/i18n';
import theme from 'src/theme';
import {
FinancialAccountContext,
FinancialAccountType,
} from '../Context/FinancialAccountsContext';
import {
AccountSummary,
AppendCategoryToCategoriesArray,
appendCategoryToCategoriesArray,
} from './AccountSummary';
import {
creditByCategories,
defaultFinancialAccountSummary,
} from './AccountSummaryMock';
import { FinancialAccountSummaryQuery } from './financialAccountSummary.generated';

const accountListId = 'accountListId';
const financialAccountId = 'financialAccountId';
const router = {
query: { accountListId },
isReady: true,
};
const mutationSpy = jest.fn();

const Component = () => (
<I18nextProvider i18n={i18n}>
<LocalizationProvider dateAdapter={AdapterLuxon}>
<SnackbarProvider>
<ThemeProvider theme={theme}>
<TestRouter router={router}>
<GqlMockedProvider<{
FinancialAccountSummary: FinancialAccountSummaryQuery;
}>
mocks={{
FinancialAccountSummary: defaultFinancialAccountSummary,
}}
onCall={mutationSpy}
>
<FinancialAccountsWrapper>
<FinancialAccountContext.Provider
value={
{
accountListId,
financialAccountId,
} as unknown as FinancialAccountType
}
>
<AccountSummary />
</FinancialAccountContext.Provider>
</FinancialAccountsWrapper>
</GqlMockedProvider>
</TestRouter>
</ThemeProvider>
</SnackbarProvider>
</LocalizationProvider>
</I18nextProvider>
);

describe('AccountSummary', () => {
it('regular', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Category')).toBeInTheDocument();
expect(getByText('Total')).toBeInTheDocument();
expect(getByText('Opening Balance')).toBeInTheDocument();
expect(getByText('Income')).toBeInTheDocument();
expect(getByText('Total Income')).toBeInTheDocument();
expect(getByText('Expenses')).toBeInTheDocument();
expect(getByText('Total Expenses')).toBeInTheDocument();
expect(getByText('Surplus/Deficit')).toBeInTheDocument();
expect(getByText('Balance')).toBeInTheDocument();
});

it('should append the categories to the array', async () => {
const categoryArray: AppendCategoryToCategoriesArray['categoryArray'] = [];
appendCategoryToCategoriesArray({
categories:
creditByCategories as AppendCategoryToCategoriesArray['categories'],
categoryArray,
index: 0,
});

expect(categoryArray).toHaveLength(2);
expect(categoryArray).toEqual([
{
id: '111',
name: 'Category 1',
amounts: [5000],
},
{
id: '222',
name: 'Code 2',
amounts: [5000],
},
]);

appendCategoryToCategoriesArray({
categories: [
{
...creditByCategories[0],
amount: '-3000',
},
{
...creditByCategories[1],
amount: '-6000',
},
] as AppendCategoryToCategoriesArray['categories'],
categoryArray,
index: 1,
});

expect(categoryArray).toHaveLength(2);
expect(categoryArray).toEqual([
{
id: '111',
name: 'Category 1',
amounts: [5000, 3000],
},
{
id: '222',
name: 'Code 2',
amounts: [5000, 6000],
},
]);
});

it('should show correct months', async () => {
const { getByText, findByText, queryByText } = render(<Component />);

expect(await findByText('Jan 24')).toBeInTheDocument();
expect(getByText('Feb 24')).toBeInTheDocument();
expect(getByText('Mar 24')).toBeInTheDocument();
expect(queryByText('Apr 24')).not.toBeInTheDocument();
});

it('should format number to correctly', async () => {
const { getByText, findByText } = render(<Component />);
// Turning '-10001.25' into '10,001'
expect(await findByText('10,002')).toBeInTheDocument();

// Turning '5684' to '-5,684'
expect(getByText('-5,684')).toBeInTheDocument();
});

it('should show correct data for Opening Balance', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Opening Balance')).toBeInTheDocument();
expect(getByText('10,002')).toBeInTheDocument();
expect(getByText('9,005')).toBeInTheDocument();
expect(getByText('12,000')).toBeInTheDocument();
expect(getByText('31,000')).toBeInTheDocument();
});

it('should render the categories', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Category 1')).toBeInTheDocument();
// Should show category code if name is null/undefined
expect(getByText('Code 2')).toBeInTheDocument();
expect(getByText('Negative Category 1')).toBeInTheDocument();
// Should show category code if name is null/undefined
expect(getByText('Negative Code 2')).toBeInTheDocument();
});

it('should show correct data for Total Income', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Total Income')).toBeInTheDocument();
expect(getByText('5,555')).toBeInTheDocument();
expect(getByText('6,666')).toBeInTheDocument();
expect(getByText('3,333')).toBeInTheDocument();
expect(getByText('14,444')).toBeInTheDocument();
});

it('should show correct data for Total Expenses', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Total Expenses')).toBeInTheDocument();
expect(getByText('2,895')).toBeInTheDocument();
expect(getByText('1,689')).toBeInTheDocument();
expect(getByText('2,689')).toBeInTheDocument();
expect(getByText('5,689')).toBeInTheDocument();
});

it('should show correct data for Surplus/Deficit', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Surplus/Deficit')).toBeInTheDocument();
expect(getByText('-5,684')).toBeInTheDocument();
expect(getByText('-1,864')).toBeInTheDocument();
expect(getByText('-3,864')).toBeInTheDocument();
expect(getByText('-6,864')).toBeInTheDocument();
});

it('should show correct data for Balance', async () => {
const { getByText, findByText } = render(<Component />);

expect(await findByText('Balance')).toBeInTheDocument();
expect(getByText('7,000')).toBeInTheDocument();
expect(getByText('8,000')).toBeInTheDocument();
expect(getByText('10,000')).toBeInTheDocument();
expect(getByText('25,000')).toBeInTheDocument();
});
});
Loading

0 comments on commit 90c7871

Please sign in to comment.