feat: wip multipe transactions categorization

This commit is contained in:
Ahmed Bouhuolia
2024-08-01 13:44:49 +02:00
parent 47dd767b3a
commit bed281a637
5 changed files with 40 additions and 14 deletions

View File

@@ -1,7 +1,8 @@
// @ts-nocheck // @ts-nocheck
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import * as R from 'ramda'; import * as R from 'ramda';
import { useEffect, useState } from 'react'; import { useEffect, useState, useMemo } from 'react';
import { uniq } from 'lodash';
import { AnchorButton, Button, Intent, Tag, Text } from '@blueprintjs/core'; import { AnchorButton, Button, Intent, Tag, Text } from '@blueprintjs/core';
import { FastField, FastFieldProps, Formik, useFormikContext } from 'formik'; import { FastField, FastFieldProps, Formik, useFormikContext } from 'formik';
import { AppToaster, Box, FormatNumber, Group, Stack } from '@/components'; import { AppToaster, Box, FormatNumber, Group, Stack } from '@/components';
@@ -25,9 +26,9 @@ import {
WithBankingActionsProps, WithBankingActionsProps,
withBankingActions, withBankingActions,
} from '../withBankingActions'; } from '../withBankingActions';
import styles from './CategorizeTransactionAside.module.scss';
import { MatchingReconcileTransactionForm } from './MatchingReconcileTransactionAside/MatchingReconcileTransactionForm';
import { withBanking } from '../withBanking'; import { withBanking } from '../withBanking';
import { MatchingReconcileTransactionForm } from './MatchingReconcileTransactionAside/MatchingReconcileTransactionForm';
import styles from './CategorizeTransactionAside.module.scss';
const initialValues = { const initialValues = {
matched: {}, matched: {},
@@ -40,10 +41,22 @@ const initialValues = {
function MatchingBankTransactionRoot({ function MatchingBankTransactionRoot({
// #withBankingActions // #withBankingActions
closeMatchingTransactionAside, closeMatchingTransactionAside,
// #withBanking
transactionsToCategorizeIdsSelected,
}) { }) {
const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot(); const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot();
const { mutateAsync: matchTransaction } = useMatchUncategorizedTransaction(); const { mutateAsync: matchTransaction } = useMatchUncategorizedTransaction();
const selectedTransactionsIds = useMemo(
() =>
uniq([
...transactionsToCategorizeIdsSelected,
uncategorizedTransactionId,
]),
[uncategorizedTransactionId, transactionsToCategorizeIdsSelected],
);
// Handles the form submitting. // Handles the form submitting.
const handleSubmit = ( const handleSubmit = (
values: MatchingTransactionFormValues, values: MatchingTransactionFormValues,
@@ -91,7 +104,7 @@ function MatchingBankTransactionRoot({
return ( return (
<MatchingTransactionBoot <MatchingTransactionBoot
uncategorizedTransactionId={uncategorizedTransactionId} uncategorizedTransactionsIds={selectedTransactionsIds}
> >
<Formik initialValues={initialValues} onSubmit={handleSubmit}> <Formik initialValues={initialValues} onSubmit={handleSubmit}>
<MatchingBankTransactionFormContent /> <MatchingBankTransactionFormContent />
@@ -100,9 +113,12 @@ function MatchingBankTransactionRoot({
); );
} }
export const MatchingBankTransaction = R.compose(withBankingActions)( export const MatchingBankTransaction = R.compose(
MatchingBankTransactionRoot, withBankingActions,
); withBanking(({ transactionsToCategorizeIdsSelected }) => ({
transactionsToCategorizeIdsSelected,
})),
)(MatchingBankTransactionRoot);
/** /**
* Matching bank transaction form content. * Matching bank transaction form content.

View File

@@ -18,12 +18,12 @@ const RuleFormBootContext = createContext<MatchingTransactionBootValues>(
); );
interface RuleFormBootProps { interface RuleFormBootProps {
uncategorizedTransactionId: number; uncategorizedTransactionsIds: Array<number>;
children: React.ReactNode; children: React.ReactNode;
} }
function MatchingTransactionBoot({ function MatchingTransactionBoot({
uncategorizedTransactionId, uncategorizedTransactionsIds,
...props ...props
}: RuleFormBootProps) { }: RuleFormBootProps) {
const { const {
@@ -31,7 +31,7 @@ function MatchingTransactionBoot({
isLoading: isMatchingTransactionsLoading, isLoading: isMatchingTransactionsLoading,
isFetching: isMatchingTransactionsFetching, isFetching: isMatchingTransactionsFetching,
isSuccess: isMatchingTransactionsSuccess, isSuccess: isMatchingTransactionsSuccess,
} = useGetBankTransactionsMatches(uncategorizedTransactionId); } = useGetBankTransactionsMatches(uncategorizedTransactionsIds);
const possibleMatches = defaultTo(matchingTransactions?.possibleMatches, []); const possibleMatches = defaultTo(matchingTransactions?.possibleMatches, []);
const perfectMatchesCount = matchingTransactions?.perfectMatches?.length || 0; const perfectMatchesCount = matchingTransactions?.perfectMatches?.length || 0;

View File

@@ -19,6 +19,9 @@ export const withBanking = (mapState) => {
excludedTransactionsIdsSelected: state.plaid.excludedTransactionsSelected, excludedTransactionsIdsSelected: state.plaid.excludedTransactionsSelected,
isMultipleCategorization: state.plaid.isMultipleCategorization, isMultipleCategorization: state.plaid.isMultipleCategorization,
transactionsToCategorizeIdsSelected:
state.plaid.transactionsToCategorizeSelected,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -168,7 +168,9 @@ export function useBankRule(
); );
} }
type GetBankTransactionsMatchesValue = number; interface GetBankTransactionsMatchesValue {
uncategorizeTransactionsIds: Array<number>;
}
interface GetBankTransactionsMatchesResponse { interface GetBankTransactionsMatchesResponse {
perfectMatches: Array<any>; perfectMatches: Array<any>;
possibleMatches: Array<any>; possibleMatches: Array<any>;
@@ -180,16 +182,18 @@ interface GetBankTransactionsMatchesResponse {
* @returns {UseQueryResult<GetBankTransactionsMatchesResponse, Error>} * @returns {UseQueryResult<GetBankTransactionsMatchesResponse, Error>}
*/ */
export function useGetBankTransactionsMatches( export function useGetBankTransactionsMatches(
uncategorizedTransactionId: number, uncategorizeTransactionsIds: Array<number>,
options?: UseQueryOptions<GetBankTransactionsMatchesResponse, Error>, options?: UseQueryOptions<GetBankTransactionsMatchesResponse, Error>,
): UseQueryResult<GetBankTransactionsMatchesResponse, Error> { ): UseQueryResult<GetBankTransactionsMatchesResponse, Error> {
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useQuery<GetBankTransactionsMatchesResponse, Error>( return useQuery<GetBankTransactionsMatchesResponse, Error>(
[QUERY_KEY.BANK_TRANSACTION_MATCHES, uncategorizedTransactionId], [QUERY_KEY.BANK_TRANSACTION_MATCHES, uncategorizeTransactionsIds],
() => () =>
apiRequest apiRequest
.get(`/cashflow/transactions/${uncategorizedTransactionId}/matches`) .get(`/cashflow/transactions/matches`, {
params: { uncategorizeTransactionsIds },
})
.then((res) => transformToCamelCase(res.data)), .then((res) => transformToCamelCase(res.data)),
options, options,
); );

View File

@@ -195,3 +195,6 @@ export const getOpenMatchingTransactionAside = (state: any) =>
export const isMultipleCategorization = (state: any) => export const isMultipleCategorization = (state: any) =>
state.plaid.enableMultipleCategorization; state.plaid.enableMultipleCategorization;
export const getTransactionsToCategorizeIdsSelected = (state: any) =>
state.plaid.transactionsToCategorizeSelected;