From 90c78711c921bb8507993fa14eb5006201c3f89b Mon Sep 17 00:00:00 2001 From: Daniel Bisgrove Date: Thu, 10 Oct 2024 10:52:47 -0400 Subject: [PATCH] 4. Summary page --- pages/api/Schema/index.ts | 6 + .../financialAccounts/datahandler.ts | 38 ++ .../financialAccounts.graphql | 35 ++ .../financialAccounts/resolvers.ts | 16 + pages/api/graphql-rest.page.ts | 34 +- .../AccountSummary/AccountSummary.test.tsx | 216 ++++++++++ .../AccountSummary/AccountSummary.tsx | 384 +++++++++++++++++- .../AccountSummary/AccountSummaryMock.ts | 143 +++++++ .../financialAccountSummary.graphql | 33 ++ src/lib/intlFormat.ts | 3 +- 10 files changed, 900 insertions(+), 8 deletions(-) create mode 100644 pages/api/Schema/reports/financialAccounts/financialAccounts/datahandler.ts create mode 100644 pages/api/Schema/reports/financialAccounts/financialAccounts/financialAccounts.graphql create mode 100644 pages/api/Schema/reports/financialAccounts/financialAccounts/resolvers.ts create mode 100644 src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.test.tsx create mode 100644 src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummaryMock.ts create mode 100644 src/components/Reports/FinancialAccountsReport/AccountSummary/financialAccountSummary.graphql diff --git a/pages/api/Schema/index.ts b/pages/api/Schema/index.ts index 4ccf32fe13..aa8aaffc29 100644 --- a/pages/api/Schema/index.ts +++ b/pages/api/Schema/index.ts @@ -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'; @@ -127,6 +129,10 @@ const schema = buildSubgraphSchema([ typeDefs: DeleteTagsTypeDefs, resolvers: DeleteTagsResolvers, }, + { + typeDefs: FinancialAccountSummaryTypeDefs, + resolvers: FinancialAccountSummaryResolvers, + }, ...integrationSchema, ...organizationSchema, ...preferencesSchema, diff --git a/pages/api/Schema/reports/financialAccounts/financialAccounts/datahandler.ts b/pages/api/Schema/reports/financialAccounts/financialAccounts/datahandler.ts new file mode 100644 index 0000000000..8aeaa5a242 --- /dev/null +++ b/pages/api/Schema/reports/financialAccounts/financialAccounts/datahandler.ts @@ -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; +}; diff --git a/pages/api/Schema/reports/financialAccounts/financialAccounts/financialAccounts.graphql b/pages/api/Schema/reports/financialAccounts/financialAccounts/financialAccounts.graphql new file mode 100644 index 0000000000..fcff761c40 --- /dev/null +++ b/pages/api/Schema/reports/financialAccounts/financialAccounts/financialAccounts.graphql @@ -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 +} diff --git a/pages/api/Schema/reports/financialAccounts/financialAccounts/resolvers.ts b/pages/api/Schema/reports/financialAccounts/financialAccounts/resolvers.ts new file mode 100644 index 0000000000..dcc43de603 --- /dev/null +++ b/pages/api/Schema/reports/financialAccounts/financialAccounts/resolvers.ts @@ -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, + ); + }, + }, +}; diff --git a/pages/api/graphql-rest.page.ts b/pages/api/graphql-rest.page.ts index 37cc299dc5..ef5803ba4a 100644 --- a/pages/api/graphql-rest.page.ts +++ b/pages/api/graphql-rest.page.ts @@ -109,6 +109,7 @@ import { FinancialAccountResponse, setActiveFinancialAccount, } from './Schema/reports/financialAccounts/datahandler'; +import { financialAccountSummaryHandler } from './Schema/reports/financialAccounts/financialAccounts/datahandler'; import { FourteenMonthReportResponse, mapFourteenMonthReport, @@ -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( @@ -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}`, diff --git a/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.test.tsx b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.test.tsx new file mode 100644 index 0000000000..2e94986a03 --- /dev/null +++ b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.test.tsx @@ -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 = () => ( + + + + + + + mocks={{ + FinancialAccountSummary: defaultFinancialAccountSummary, + }} + onCall={mutationSpy} + > + + + + + + + + + + + +); + +describe('AccountSummary', () => { + it('regular', async () => { + const { getByText, findByText } = render(); + + 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(); + + 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(); + // 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(); + + 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(); + + 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(); + + 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(); + + 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(); + + 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(); + + 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(); + }); +}); diff --git a/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.tsx b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.tsx index 4de130a6fb..e61a7b3974 100644 --- a/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.tsx +++ b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummary.tsx @@ -1,6 +1,384 @@ -import React from 'react'; -import { Box } from '@mui/material'; +import React, { useContext, useMemo } from 'react'; +import { + Box, + CircularProgress, + Divider, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Typography, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import { DateTime } from 'luxon'; +import { useTranslation } from 'react-i18next'; +import { Maybe } from 'src/graphql/types.generated'; +import { useLocale } from 'src/hooks/useLocale'; +import { monthYearFormat, numberFormat } from 'src/lib/intlFormat'; +import theme from 'src/theme'; +import { + FinancialAccountContext, + FinancialAccountType, +} from '../Context/FinancialAccountsContext'; +import { FinancialAccountHeader } from '../Header/Header'; +import { + FinancialAccountCategoriesFragment, + useFinancialAccountSummaryQuery, +} from './financialAccountSummary.generated'; + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + padding: `${theme.spacing(1)} ${theme.spacing(2)}`, +})); + +interface Periods { + startDateFormatted: string; + startDate: string; + endDate: string; +} + +interface Category { + id: string; + name: string; + amounts: number[]; +} + +export const formatNumber = ( + numberAsString?: string | number | null, + makeAbsolute = true, +) => { + const number = + typeof numberAsString === 'string' + ? Number(numberAsString) + : numberAsString ?? 0; + return Math.ceil(makeAbsolute ? Math.abs(number) : number); +}; + +export interface AppendCategoryToCategoriesArray { + categories: Maybe[]; + categoryArray: Category[]; + index: number; +} + +export const appendCategoryToCategoriesArray = ({ + categories, + categoryArray, + index, +}: AppendCategoryToCategoriesArray) => { + categories.forEach((category) => { + const id = category?.category?.id ?? ''; + const name = category?.category?.name ?? category?.category?.code ?? ''; + const amount = formatNumber(category?.amount); + if (index === 0) { + categoryArray.push({ id, name, amounts: [amount] }); + } else { + const existingCategory = categoryArray.find((c) => c.id === id); + if (existingCategory) { + existingCategory.amounts.push(amount); + } + } + }); +}; export const AccountSummary: React.FC = () => { - return AccountSummary; + const { t } = useTranslation(); + const locale = useLocale(); + const { accountListId, financialAccountId } = useContext( + FinancialAccountContext, + ) as FinancialAccountType; + + const { data } = useFinancialAccountSummaryQuery({ + variables: { + accountListId, + financialAccountId: financialAccountId ?? '', + }, + }); + + const tableData = useMemo(() => { + const credits: number[] = []; + const creditsCategories: Category[] = []; + const closingBalances: number[] = []; + const debits: number[] = []; + const debitsCategories: Category[] = []; + const openingBalances: number[] = []; + const periods: Periods[] = []; + const surplus: number[] = []; + + data?.financialAccountSummary.forEach((item, idx) => { + if (!item) { + return; + } + + // Credits + credits.push(formatNumber(item.credits)); + + // Closing Balances + openingBalances.push(formatNumber(item.openingBalance)); + + // Debits + debits.push(formatNumber(item.debits)); + + // Closing Balances + closingBalances.push(formatNumber(item.closingBalance)); + + // Surplus + /** + * If the first character of the `item.difference` is '-', it removes the '-' character. + * Otherwise, it prepends the '-' character to the `item.difference` value. + */ + const difference = + item.difference?.[0] === '-' + ? item.difference.substring(1) + : `-${item.difference}`; + surplus.push(formatNumber(difference, false)); + + // Periods + const startDateFormatted = monthYearFormat( + DateTime.fromISO(item?.startDate ?? '').month, + DateTime.fromISO(item?.startDate ?? '').year, + locale, + false, + ); + periods.push({ + startDateFormatted: + idx === data.financialAccountSummary.length - 1 + ? 'Total' + : startDateFormatted, + startDate: item?.startDate ?? '', + endDate: item?.endDate ?? '', + }); + + // Credits Categories + appendCategoryToCategoriesArray({ + categories: item.creditByCategories, + categoryArray: creditsCategories, + index: idx, + }); + + // Debits Categories + appendCategoryToCategoriesArray({ + categories: item.debitByCategories, + categoryArray: debitsCategories, + index: idx, + }); + }); + + return { + closingBalances, + credits, + creditsCategories: creditsCategories.sort((a, b) => + a.name.localeCompare(b.name), + ), + debits, + debitsCategories: debitsCategories.sort((a, b) => + a.name.localeCompare(b.name), + ), + openingBalances, + periods, + surplus, + }; + }, [data]); + + return ( + <> + + + {!data && ( + + + + )} + + {data && ( + + + + + + + {t('Category')} + + {tableData.periods?.map((period, idx) => { + return ( + + {period.startDateFormatted} + + ); + })} + + + + + {/* Opening Balance */} + + + + {t('Opening Balance')} + + + {tableData.openingBalances?.map((balance, idx) => { + return ( + + {numberFormat(balance, locale)} + + ); + })} + + {/* Income header */} + + + {t('Income')} + + {tableData.periods?.map((_, idx) => { + return ( + + ); + })} + + + {/* Income Categories */} + {tableData.creditsCategories?.map((category, idx) => { + return ( + + + + {category.name} + + + + {category.amounts.map((amount, idx) => ( + + {numberFormat(amount, locale)} + + ))} + + ); + })} + + {/* Total Income */} + + + + {t('Total Income')} + + + {tableData.credits?.map((credit, idx) => { + return ( + + + {numberFormat(credit, locale)} + + + ); + })} + + + {/* Expenses header */} + + + {t('Expenses')} + + {tableData.periods?.map((_, idx) => { + return ( + + ); + })} + + + {/* Expenses Categories */} + {tableData.debitsCategories?.map((category, idx) => { + return ( + + + + {category.name} + + + + {category.amounts.map((amount, idx) => ( + + {numberFormat(amount, locale)} + + ))} + + ); + })} + + {/* Total Expenses */} + + + + {t('Total Expenses')} + + + {tableData.debits?.map((credit, idx) => { + return ( + + + {numberFormat(credit, locale)} + + + ); + })} + + + {/* Surplus */} + + + + {t('Surplus/Deficit')} + + + {tableData.surplus?.map((value, idx) => { + return ( + + + {numberFormat(value, locale)} + + + ); + })} + + + {/* Closing Balance */} + + + + {t('Balance')} + + + {tableData.closingBalances?.map((balance, idx) => { + return ( + + + {numberFormat(balance, locale)} + + + ); + })} + + +
+
+
+ )} + + ); }; diff --git a/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummaryMock.ts b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummaryMock.ts new file mode 100644 index 0000000000..e47944c033 --- /dev/null +++ b/src/components/Reports/FinancialAccountsReport/AccountSummary/AccountSummaryMock.ts @@ -0,0 +1,143 @@ +export const creditByCategories = [ + { + amount: '-5000', + category: { + id: '111', + name: 'Category 1', + code: 'Code 1', + }, + }, + { + amount: '-5000', + category: { + id: '222', + name: null, + code: 'Code 2', + }, + }, +]; +const debitByCategories = [ + { + amount: '9000', + category: { + id: '333', + name: 'Negative Category 1', + code: 'Negative Code 1', + }, + }, + { + amount: '4000', + category: { + id: '444', + name: null, + code: 'Negative Code 2', + }, + }, +]; + +export const defaultFinancialAccountSummary = { + financialAccountSummary: [ + { + id: '1', + closingBalance: '-7000', + credits: '-5555', + debits: '2895', + difference: '5684', + endDate: '2024-01-31', + openingBalance: '-10001.25', + startDate: '2024-01-01', + creditByCategories, + debitByCategories, + }, + { + id: '2', + closingBalance: '-8000', + credits: '-6666', + debits: '1689', + difference: '1864', + endDate: '2024-02-29', + openingBalance: '-9005', + startDate: '2024-02-01', + creditByCategories: [ + { + ...creditByCategories[0], + amount: '-3000', + }, + { + ...creditByCategories[1], + amount: '-6000', + }, + ], + debitByCategories: [ + { + ...debitByCategories[0], + amount: '4000', + }, + { + ...debitByCategories[1], + amount: '1000', + }, + ], + }, + { + id: '3', + closingBalance: '-10000', + credits: '-3333', + debits: '2689', + difference: '3864', + endDate: '2024-03-31', + openingBalance: '-12000', + startDate: '2024-03-01', + creditByCategories: [ + { + ...creditByCategories[0], + amount: '-4500', + }, + { + ...creditByCategories[1], + amount: '-3000', + }, + ], + debitByCategories: [ + { + ...debitByCategories[0], + amount: '2000', + }, + { + ...debitByCategories[1], + amount: '4000', + }, + ], + }, + { + id: '4', + closingBalance: '-25000', + credits: '-14444', + debits: '5689', + difference: '6864', + endDate: '2024-03-31', + openingBalance: '-31000', + startDate: '2024-01-01', + creditByCategories: [ + { + ...creditByCategories[0], + amount: '-19000', + }, + { + ...creditByCategories[1], + amount: '-23000', + }, + ], + debitByCategories: [ + { + ...debitByCategories[0], + amount: '19500', + }, + { + ...debitByCategories[1], + amount: '23000', + }, + ], + }, + ], +}; diff --git a/src/components/Reports/FinancialAccountsReport/AccountSummary/financialAccountSummary.graphql b/src/components/Reports/FinancialAccountsReport/AccountSummary/financialAccountSummary.graphql new file mode 100644 index 0000000000..643dabb734 --- /dev/null +++ b/src/components/Reports/FinancialAccountsReport/AccountSummary/financialAccountSummary.graphql @@ -0,0 +1,33 @@ +query FinancialAccountSummary($accountListId: ID!, $financialAccountId: ID!) { + financialAccountSummary( + input: { + accountListId: $accountListId + financialAccountId: $financialAccountId + } + ) { + id + closingBalance + credits + debits + difference + endDate + openingBalance + startDate + creditByCategories { + ...FinancialAccountCategories + } + debitByCategories { + ...FinancialAccountCategories + } + } +} + +fragment FinancialAccountCategories on FinancialAccountSummaryCategory { + id + amount + category { + id + code + name + } +} diff --git a/src/lib/intlFormat.ts b/src/lib/intlFormat.ts index ea9421761d..2c5c7c9194 100644 --- a/src/lib/intlFormat.ts +++ b/src/lib/intlFormat.ts @@ -50,10 +50,11 @@ export const monthYearFormat = ( month: number, year: number, locale: string, + fullYear = true, ): string => new Intl.DateTimeFormat(locale, { month: 'short', - year: 'numeric', + year: fullYear ? 'numeric' : '2-digit', }).format(DateTime.local(year, month, 1).toJSDate()); export const dateFormat = (date: DateTime | null, locale: string): string => {