mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
feat: wip matching bank transactions
This commit is contained in:
@@ -89,6 +89,27 @@ export default class UncategorizedCashflowTransaction extends mixin(
|
|||||||
return !!this.recognizedTransactionId;
|
return !!this.recognizedTransactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model modifiers.
|
||||||
|
*/
|
||||||
|
static get modifiers() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Filters the not excluded transactions.
|
||||||
|
*/
|
||||||
|
notExcluded(query) {
|
||||||
|
query.whereNull('excluded');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the excluded transactions.
|
||||||
|
*/
|
||||||
|
excluded(query) {
|
||||||
|
query.where('excluded', true)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class UnexcludeBankTransaction {
|
|||||||
await UncategorizedCashflowTransaction.query(trx)
|
await UncategorizedCashflowTransaction.query(trx)
|
||||||
.findById(uncategorizedTransactionId)
|
.findById(uncategorizedTransactionId)
|
||||||
.patch({
|
.patch({
|
||||||
excluded: false,
|
excluded: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
import { GetMatchedTransactionBillsTransformer } from './GetMatchedTransactionBillsTransformer';
|
import { GetMatchedTransactionBillsTransformer } from './GetMatchedTransactionBillsTransformer';
|
||||||
import { GetMatchedTransactionsFilter } from './types';
|
import { GetMatchedTransactionsFilter, MatchedTransactionPOJO } from './types';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
|
|
||||||
@@ -24,7 +24,9 @@ export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType
|
|||||||
) {
|
) {
|
||||||
const { Bill } = this.tenancy.models(tenantId);
|
const { Bill } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const bills = await Bill.query();
|
const bills = await Bill.query().onBuild((q) => {
|
||||||
|
q.whereNotExists(Bill.relatedQuery('matchedBankTransaction'));
|
||||||
|
});
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -32,4 +34,25 @@ export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType
|
|||||||
new GetMatchedTransactionBillsTransformer()
|
new GetMatchedTransactionBillsTransformer()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given bill matched transaction.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} transactionId
|
||||||
|
* @returns {Promise<MatchedTransactionPOJO>}
|
||||||
|
*/
|
||||||
|
public async getMatchedTransaction(
|
||||||
|
tenantId: number,
|
||||||
|
transactionId: number
|
||||||
|
): Promise<MatchedTransactionPOJO> {
|
||||||
|
const { Bill } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const bill = await Bill.query().findById(transactionId).throwIfNotFound();
|
||||||
|
|
||||||
|
return this.transformer.transform(
|
||||||
|
tenantId,
|
||||||
|
bill,
|
||||||
|
new GetMatchedTransactionBillsTransformer()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { GetMatchedTransactionsFilter } from './types';
|
import { GetMatchedTransactionsFilter, MatchedTransactionPOJO } from './types';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
@@ -46,4 +46,27 @@ export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByTy
|
|||||||
new GetMatchedTransactionExpensesTransformer()
|
new GetMatchedTransactionExpensesTransformer()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given matched expense transaction.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} transactionId
|
||||||
|
* @returns {GetMatchedTransactionExpensesTransformer-}
|
||||||
|
*/
|
||||||
|
public async getMatchedTransaction(
|
||||||
|
tenantId: number,
|
||||||
|
transactionId: number
|
||||||
|
): Promise<MatchedTransactionPOJO> {
|
||||||
|
const { Expense } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const expense = await Expense.query()
|
||||||
|
.findById(transactionId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
return this.transformer.transform(
|
||||||
|
tenantId,
|
||||||
|
expense,
|
||||||
|
new GetMatchedTransactionExpensesTransformer()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ export class GetMatchedTransactionsByInvoices extends GetMatchedTransactionsByTy
|
|||||||
): Promise<MatchedTransactionsPOJO> {
|
): Promise<MatchedTransactionsPOJO> {
|
||||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const invoices = await SaleInvoice.query();
|
const invoices = await SaleInvoice.query().onBuild((q) => {
|
||||||
|
q.whereNotExists(SaleInvoice.relatedQuery('matchedBankTransaction'));
|
||||||
|
});
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
tenantId,
|
tenantId,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export class GetUncategorizedTransactions {
|
|||||||
await UncategorizedCashflowTransaction.query()
|
await UncategorizedCashflowTransaction.query()
|
||||||
.where('accountId', accountId)
|
.where('accountId', accountId)
|
||||||
.where('categorized', false)
|
.where('categorized', false)
|
||||||
|
.modify('notExcluded')
|
||||||
.withGraphFetched('account')
|
.withGraphFetched('account')
|
||||||
.orderBy('date', 'DESC')
|
.orderBy('date', 'DESC')
|
||||||
.pagination(_query.page - 1, _query.pageSize);
|
.pagination(_query.page - 1, _query.pageSize);
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
|
import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
|
||||||
import { safeCallback } from '@/utils';
|
import { safeCallback } from '@/utils';
|
||||||
|
import { Icon } from '@/components';
|
||||||
|
|
||||||
export function ActionsMenu({ payload: { onRestore }, row: { original } }) {
|
export function ActionsMenu({ payload: { onRestore }, row: { original } }) {
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem text={'Restore'} onClick={safeCallback(onRestore, original)} />
|
<MenuItem
|
||||||
|
text={'Restore'}
|
||||||
|
icon={<Icon icon="redo" iconSize={16} />}
|
||||||
|
onClick={safeCallback(onRestore, original)}
|
||||||
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function ActionsMenu({
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
text={'Exclude'}
|
text={'Exclude'}
|
||||||
onClick={safeCallback(onExclude, original)}
|
onClick={safeCallback(onExclude, original)}
|
||||||
// icon={<Icon icon="trash-16" iconSize={16} />}
|
icon={<Icon icon="disable" iconSize={16} />}
|
||||||
/>
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { Formik, Form } from 'formik';
|
import { Formik, Form } from 'formik';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { CreateCategorizeTransactionSchema } from './CategorizeTransactionForm.schema';
|
import { CreateCategorizeTransactionSchema } from './CategorizeTransactionForm.schema';
|
||||||
import { CategorizeTransactionFormContent } from './CategorizeTransactionFormContent';
|
import { CategorizeTransactionFormContent } from './CategorizeTransactionFormContent';
|
||||||
import { CategorizeTransactionFormFooter } from './CategorizeTransactionFormFooter';
|
import { CategorizeTransactionFormFooter } from './CategorizeTransactionFormFooter';
|
||||||
import { useCategorizeTransaction } from '@/hooks/query';
|
import { useCategorizeTransaction } from '@/hooks/query';
|
||||||
import { useCategorizeTransactionBoot } from './CategorizeTransactionBoot';
|
import { useCategorizeTransactionBoot } from './CategorizeTransactionBoot';
|
||||||
import { DRAWERS } from '@/constants/drawers';
|
|
||||||
import {
|
import {
|
||||||
transformToCategorizeForm,
|
transformToCategorizeForm,
|
||||||
defaultInitialValues,
|
defaultInitialValues,
|
||||||
tranformToRequest,
|
tranformToRequest,
|
||||||
} from './_utils';
|
} from './_utils';
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
import { withBankingActions } from '@/containers/CashFlow/withBankingActions';
|
||||||
import { AppToaster } from '@/components';
|
import { AppToaster } from '@/components';
|
||||||
import { Intent } from '@blueprintjs/core';
|
|
||||||
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
|
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categorize cashflow transaction form dialog content.
|
* Categorize cashflow transaction form dialog content.
|
||||||
*/
|
*/
|
||||||
function CategorizeTransactionFormRoot({
|
function CategorizeTransactionFormRoot({
|
||||||
// #withDrawerActions
|
// #withBankingActions
|
||||||
closeDrawer,
|
closeMatchingTransactionAside,
|
||||||
}) {
|
}) {
|
||||||
const { uncategorizedTransactionId, uncategorizedTransaction } =
|
const { uncategorizedTransactionId, uncategorizedTransaction } =
|
||||||
useCategorizeTransactionTabsBoot();
|
useCategorizeTransactionTabsBoot();
|
||||||
@@ -38,12 +37,12 @@ function CategorizeTransactionFormRoot({
|
|||||||
categorizeTransaction([uncategorizedTransactionId, transformedValues])
|
categorizeTransaction([uncategorizedTransactionId, transformedValues])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
closeDrawer(DRAWERS.CATEGORIZE_TRANSACTION);
|
|
||||||
|
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: 'The uncategorized transaction has been categorized.',
|
message: 'The uncategorized transaction has been categorized.',
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
|
closeMatchingTransactionAside();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
@@ -93,7 +92,7 @@ function CategorizeTransactionFormRoot({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CategorizeTransactionForm = compose(withDrawerActions)(
|
export const CategorizeTransactionForm = compose(withBankingActions)(
|
||||||
CategorizeTransactionFormRoot,
|
CategorizeTransactionFormRoot,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function MatchingBankTransaction() {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
matchTransaction({ id: uncategorizedTransactionId, values: _values })
|
matchTransaction({ id: uncategorizedTransactionId, value: _values })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
|
|||||||
@@ -223,6 +223,9 @@ export function useExcludeUncategorizedTransaction(
|
|||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries(
|
||||||
QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
|
QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
|
||||||
);
|
);
|
||||||
|
queryClient.invalidateQueries(
|
||||||
|
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
@@ -267,6 +270,9 @@ export function useUnexcludeUncategorizedTransaction(
|
|||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries(
|
||||||
QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
|
QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
|
||||||
);
|
);
|
||||||
|
queryClient.invalidateQueries(
|
||||||
|
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -617,4 +617,16 @@ export default {
|
|||||||
],
|
],
|
||||||
viewBox: '0 0 16 16',
|
viewBox: '0 0 16 16',
|
||||||
},
|
},
|
||||||
|
disable: {
|
||||||
|
path: [
|
||||||
|
'M7.99-0.01c-4.42,0-8,3.58-8,8s3.58,8,8,8s8-3.58,8-8S12.41-0.01,7.99-0.01zM1.99,7.99c0-3.31,2.69-6,6-6c1.3,0,2.49,0.42,3.47,1.12l-8.35,8.35C2.41,10.48,1.99,9.29,1.99,7.99z M7.99,13.99c-1.3,0-2.49-0.42-3.47-1.12l8.35-8.35c0.7,0.98,1.12,2.17,1.12,3.47C13.99,11.31,11.31,13.99,7.99,13.99z',
|
||||||
|
],
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
},
|
||||||
|
redo: {
|
||||||
|
path: [
|
||||||
|
'M4,11c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S5.1,11,4,11z M11,4H3.41l1.29-1.29C4.89,2.53,5,2.28,5,2c0-0.55-0.45-1-1-1C3.72,1,3.47,1.11,3.29,1.29l-3,3C0.11,4.47,0,4.72,0,5c0,0.28,0.11,0.53,0.29,0.71l3,3C3.47,8.89,3.72,9,4,9c0.55,0,1-0.45,1-1c0-0.28-0.11-0.53-0.29-0.71L3.41,6H11c1.66,0,3,1.34,3,3s-1.34,3-3,3H7v2h4c2.76,0,5-2.24,5-5S13.76,4,11,4z',
|
||||||
|
],
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user