diff --git a/packages/server/src/interfaces/CashflowService.ts b/packages/server/src/interfaces/CashflowService.ts index cabdea423..99977c31d 100644 --- a/packages/server/src/interfaces/CashflowService.ts +++ b/packages/server/src/interfaces/CashflowService.ts @@ -130,8 +130,9 @@ export interface ICommandCashflowDeletedPayload { export interface ICashflowTransactionCategorizedPayload { tenantId: number; - cashflowTransactionId: number; + uncategorizedTransaction: any; cashflowTransaction: ICashflowTransaction; + categorizeDTO: any; trx: Knex.Transaction; } export interface ICashflowTransactionUncategorizingPayload { diff --git a/packages/server/src/interfaces/Import.ts b/packages/server/src/interfaces/Import.ts new file mode 100644 index 000000000..4f6d2e069 --- /dev/null +++ b/packages/server/src/interfaces/Import.ts @@ -0,0 +1,8 @@ +import { ImportFilePreviewPOJO } from "@/services/Import/interfaces"; + + +export interface IImportFileCommitedEventPayload { + tenantId: number; + importId: number; + meta: ImportFilePreviewPOJO; +} \ No newline at end of file diff --git a/packages/server/src/loaders/eventEmitter.ts b/packages/server/src/loaders/eventEmitter.ts index 21d20c387..8595bed55 100644 --- a/packages/server/src/loaders/eventEmitter.ts +++ b/packages/server/src/loaders/eventEmitter.ts @@ -112,6 +112,7 @@ import { RecognizeSyncedBankTranasctions } from '@/services/Banking/Plaid/subscr import { UnlinkBankRuleOnDeleteBankRule } from '@/services/Banking/Rules/events/UnlinkBankRuleOnDeleteBankRule'; import { DecrementUncategorizedTransactionOnMatching } from '@/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch'; import { DecrementUncategorizedTransactionOnExclude } from '@/services/Banking/Exclude/events/DecrementUncategorizedTransactionOnExclude'; +import { DecrementUncategorizedTransactionOnCategorize } from '@/services/Cashflow/subscribers/DecrementUncategorizedTransactionOnCategorize'; export default () => { return new EventPublisher(); @@ -262,6 +263,7 @@ export const susbcribers = () => { UnlinkBankRuleOnDeleteBankRule, DecrementUncategorizedTransactionOnMatching, DecrementUncategorizedTransactionOnExclude, + DecrementUncategorizedTransactionOnCategorize, // Validate matching ValidateMatchingOnCashflowDelete, diff --git a/packages/server/src/models/UncategorizedCashflowTransaction.ts b/packages/server/src/models/UncategorizedCashflowTransaction.ts index 2418b1711..029825583 100644 --- a/packages/server/src/models/UncategorizedCashflowTransaction.ts +++ b/packages/server/src/models/UncategorizedCashflowTransaction.ts @@ -184,56 +184,4 @@ export default class UncategorizedCashflowTransaction extends mixin( }, }; } - - /** - * Updates the count of uncategorized transactions for the associated account - * based on the specified operation. - * @param {QueryContext} queryContext - The query context for the transaction. - * @param {boolean} increment - Indicates whether to increment or decrement the count. - */ - private async updateUncategorizedTransactionCount( - queryContext: QueryContext, - increment: boolean, - amount: number = 1 - ) { - const operation = increment ? 'increment' : 'decrement'; - - await Account.query(queryContext.transaction) - .findById(this.accountId) - [operation]('uncategorized_transactions', amount); - } - - /** - * Runs after insert. - * @param {QueryContext} queryContext - */ - public async $afterInsert(queryContext) { - await super.$afterInsert(queryContext); - await this.updateUncategorizedTransactionCount(queryContext, true); - } - - /** - * Runs after update. - * @param {ModelOptions} opt - * @param {QueryContext} queryContext - */ - public async $afterUpdate( - opt: ModelOptions, - queryContext: QueryContext - ): Promise { - await super.$afterUpdate(opt, queryContext); - - if (this.id && this.categorized) { - await this.updateUncategorizedTransactionCount(queryContext, false); - } - } - - /** - * Runs after delete. - * @param {QueryContext} queryContext - */ - public async $afterDelete(queryContext: QueryContext) { - await super.$afterDelete(queryContext); - await this.updateUncategorizedTransactionCount(queryContext, false); - } } diff --git a/packages/server/src/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch.ts b/packages/server/src/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch.ts index 67dda577d..8cd291f18 100644 --- a/packages/server/src/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch.ts +++ b/packages/server/src/services/Banking/Matching/events/DecrementUncategorizedTransactionsOnMatch.ts @@ -39,7 +39,6 @@ export class DecrementUncategorizedTransactionOnMatching { const transaction = await UncategorizedCashflowTransaction.query().findById( uncategorizedTransactionId ); - // await Account.query(trx) .findById(transaction.accountId) .decrement('uncategorizedTransactions', 1); @@ -60,7 +59,6 @@ export class DecrementUncategorizedTransactionOnMatching { const transaction = await UncategorizedCashflowTransaction.query().findById( uncategorizedTransactionId ); - // await Account.query(trx) .findById(transaction.accountId) .increment('uncategorizedTransactions', 1); diff --git a/packages/server/src/services/Banking/RegonizeTranasctions/RecognizeTransactionsJob.ts b/packages/server/src/services/Banking/RegonizeTranasctions/RecognizeTransactionsJob.ts index 2eee22f53..9a3d625a3 100644 --- a/packages/server/src/services/Banking/RegonizeTranasctions/RecognizeTransactionsJob.ts +++ b/packages/server/src/services/Banking/RegonizeTranasctions/RecognizeTransactionsJob.ts @@ -18,11 +18,11 @@ export class RegonizeTransactionsJob { * Triggers sending invoice mail. */ private handler = async (job, done: Function) => { - const { tenantId } = job.attrs.data; + const { tenantId, batch } = job.attrs.data; const regonizeTransactions = Container.get(RecognizeTranasctionsService); try { - await regonizeTransactions.recognizeTransactions(tenantId); + await regonizeTransactions.recognizeTransactions(tenantId, batch); done(); } catch (error) { console.log(error); diff --git a/packages/server/src/services/Banking/RegonizeTranasctions/events/TriggerRecognizedTransactions.ts b/packages/server/src/services/Banking/RegonizeTranasctions/events/TriggerRecognizedTransactions.ts index bb8c87b43..bc5285d1b 100644 --- a/packages/server/src/services/Banking/RegonizeTranasctions/events/TriggerRecognizedTransactions.ts +++ b/packages/server/src/services/Banking/RegonizeTranasctions/events/TriggerRecognizedTransactions.ts @@ -5,6 +5,8 @@ import { IBankRuleEventDeletedPayload, IBankRuleEventEditedPayload, } from '../../Rules/types'; +import { IImportFileCommitedEventPayload } from '@/interfaces/Import'; +import { Import } from '@/system/models'; @Service() export class TriggerRecognizedTransactions { @@ -27,6 +29,10 @@ export class TriggerRecognizedTransactions { events.bankRules.onDeleted, this.recognizedTransactionsOnRuleDeleted.bind(this) ); + bus.subscribe( + events.import.onImportCommitted, + this.triggerRecognizeTransactionsOnImportCommitted.bind(this) + ); } /** @@ -73,4 +79,20 @@ export class TriggerRecognizedTransactions { const payload = { tenantId }; await this.agenda.now('recognize-uncategorized-transactions-job', payload); } + + /** + * Triggers the recognize bank transactions once the imported file commit. + * @param {IImportFileCommitedEventPayload} payload - + */ + private async triggerRecognizeTransactionsOnImportCommitted({ + tenantId, + importId, + meta, + }: IImportFileCommitedEventPayload) { + const importFile = await Import.query().findOne({ importId }); + const batch = importFile.paramsParsed.batch; + const payload = { tenantId, batch }; + + await this.agenda.now('recognize-uncategorized-transactions-job', payload); + } } diff --git a/packages/server/src/services/Cashflow/CategorizeCashflowTransaction.ts b/packages/server/src/services/Cashflow/CategorizeCashflowTransaction.ts index ba8f7c078..43ddfe603 100644 --- a/packages/server/src/services/Cashflow/CategorizeCashflowTransaction.ts +++ b/packages/server/src/services/Cashflow/CategorizeCashflowTransaction.ts @@ -84,20 +84,23 @@ export class CategorizeCashflowTransaction { cashflowTransactionDTO ); // Updates the uncategorized transaction as categorized. - await UncategorizedCashflowTransaction.query(trx).patchAndFetchById( - uncategorizedTransactionId, - { - categorized: true, - categorizeRefType: 'CashflowTransaction', - categorizeRefId: cashflowTransaction.id, - } - ); + const uncategorizedTransaction = + await UncategorizedCashflowTransaction.query(trx).patchAndFetchById( + uncategorizedTransactionId, + { + categorized: true, + categorizeRefType: 'CashflowTransaction', + categorizeRefId: cashflowTransaction.id, + } + ); // Triggers `onCashflowTransactionCategorized` event. await this.eventPublisher.emitAsync( events.cashflow.onTransactionCategorized, { tenantId, - // cashflowTransaction, + cashflowTransaction, + uncategorizedTransaction, + categorizeDTO, trx, } as ICashflowTransactionCategorizedPayload ); diff --git a/packages/server/src/services/Cashflow/UncategorizedTransactionsImportable.ts b/packages/server/src/services/Cashflow/UncategorizedTransactionsImportable.ts index a08a27f07..6350dc406 100644 --- a/packages/server/src/services/Cashflow/UncategorizedTransactionsImportable.ts +++ b/packages/server/src/services/Cashflow/UncategorizedTransactionsImportable.ts @@ -1,6 +1,7 @@ import { Inject, Service } from 'typedi'; import { Knex } from 'knex'; import * as yup from 'yup'; +import uniqid from 'uniqid'; import { Importable } from '../Import/Importable'; import { CreateUncategorizedTransaction } from './CreateUncategorizedTransaction'; import { CreateUncategorizedTransactionDTO } from '@/interfaces'; @@ -15,6 +16,7 @@ export class UncategorizedTransactionsImportable extends Importable { @Inject() private tenancy: HasTenancyService; + /** * Passing the sheet DTO to create uncategorized transaction. * @param {number} tenantId @@ -43,6 +45,7 @@ export class UncategorizedTransactionsImportable extends Importable { return { ...createDTO, accountId: context.import.paramsParsed.accountId, + batch: context.import.paramsParsed.batch, }; } @@ -54,6 +57,9 @@ export class UncategorizedTransactionsImportable extends Importable { return BankTransactionsSampleData; } + // ------------------ + // # Params + // ------------------ /** * Params validation schema. * @returns {ValidationSchema[]} @@ -79,4 +85,17 @@ export class UncategorizedTransactionsImportable extends Importable { await Account.query().findById(params.accountId).throwIfNotFound({}); } } + + /** + * Transformes the import params before storing them. + * @param {Record} parmas + */ + public transformParams(parmas: Record) { + const batch = uniqid(); + + return { + ...parmas, + batch, + }; + } } diff --git a/packages/server/src/services/Cashflow/subscribers/DecrementUncategorizedTransactionOnCategorize.ts b/packages/server/src/services/Cashflow/subscribers/DecrementUncategorizedTransactionOnCategorize.ts new file mode 100644 index 000000000..eb56d67dd --- /dev/null +++ b/packages/server/src/services/Cashflow/subscribers/DecrementUncategorizedTransactionOnCategorize.ts @@ -0,0 +1,56 @@ +import { Inject, Service } from 'typedi'; +import events from '@/subscribers/events'; +import HasTenancyService from '@/services/Tenancy/TenancyService'; +import { + ICashflowTransactionCategorizedPayload, + ICashflowTransactionUncategorizedPayload, +} from '@/interfaces'; + +@Service() +export class DecrementUncategorizedTransactionOnCategorize { + @Inject() + private tenancy: HasTenancyService; + /** + * Constructor method. + */ + public attach(bus) { + bus.subscribe( + events.cashflow.onTransactionCategorized, + this.decrementUnCategorizedTransactionsOnCategorized.bind(this) + ); + bus.subscribe( + events.cashflow.onTransactionUncategorized, + this.incrementUnCategorizedTransactionsOnUncategorized.bind(this) + ); + } + + /** + * Decrement the uncategoirzed transactions on the account once categorizing. + * @param {ICashflowTransactionCategorizedPayload} + */ + public async decrementUnCategorizedTransactionsOnCategorized({ + tenantId, + uncategorizedTransaction, + }: ICashflowTransactionCategorizedPayload) { + const { Account } = this.tenancy.models(tenantId); + + await Account.query() + .findById(uncategorizedTransaction.accountId) + .decrement('uncategorizedTransactions', 1); + } + + /** + * Increment the uncategorized transaction on the given account on uncategorizing. + * @param {IManualJournalDeletingPayload} + */ + public async incrementUnCategorizedTransactionsOnUncategorized({ + tenantId, + uncategorizedTransaction, + }: ICashflowTransactionUncategorizedPayload) { + const { Account } = this.tenancy.models(tenantId); + + await Account.query() + .findById(uncategorizedTransaction.accountId) + .increment('uncategorizedTransactions', 1); + } +} diff --git a/packages/server/src/services/Import/ImportFileCommon.ts b/packages/server/src/services/Import/ImportFileCommon.ts index 739927e6c..4e9179bdd 100644 --- a/packages/server/src/services/Import/ImportFileCommon.ts +++ b/packages/server/src/services/Import/ImportFileCommon.ts @@ -15,14 +15,10 @@ import { ServiceError } from '@/exceptions'; import { getUniqueImportableValue, trimObject } from './_utils'; import { ImportableResources } from './ImportableResources'; import ResourceService from '../Resource/ResourceService'; -import HasTenancyService from '../Tenancy/TenancyService'; import { Import } from '@/system/models'; @Service() export class ImportFileCommon { - @Inject() - private tenancy: HasTenancyService; - @Inject() private importFileValidator: ImportFileDataValidator; diff --git a/packages/server/src/services/Import/ImportFileProcessCommit.ts b/packages/server/src/services/Import/ImportFileProcessCommit.ts new file mode 100644 index 000000000..14c229fec --- /dev/null +++ b/packages/server/src/services/Import/ImportFileProcessCommit.ts @@ -0,0 +1,47 @@ +import { Inject, Service } from 'typedi'; +import HasTenancyService from '../Tenancy/TenancyService'; +import { ImportFilePreviewPOJO } from './interfaces'; +import { ImportFileProcess } from './ImportFileProcess'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; +import { IImportFileCommitedEventPayload } from '@/interfaces/Import'; + +@Service() +export class ImportFileProcessCommit { + @Inject() + private tenancy: HasTenancyService; + + @Inject() + private importFile: ImportFileProcess; + + @Inject() + private eventPublisher: EventPublisher; + + /** + * Commits the imported file. + * @param {number} tenantId + * @param {number} importId + * @returns {Promise} + */ + public async commit( + tenantId: number, + importId: number + ): Promise { + const knex = this.tenancy.knex(tenantId); + const trx = await knex.transaction({ isolationLevel: 'read uncommitted' }); + + const meta = await this.importFile.import(tenantId, importId, trx); + + // Commit the successed transaction. + await trx.commit(); + + // Triggers `onImportFileCommitted` event. + await this.eventPublisher.emitAsync(events.import.onImportCommitted, { + meta, + importId, + tenantId, + } as IImportFileCommitedEventPayload); + + return meta; + } +} diff --git a/packages/server/src/services/Import/ImportResourceApplication.ts b/packages/server/src/services/Import/ImportResourceApplication.ts index e4a7cb2f9..34df746c6 100644 --- a/packages/server/src/services/Import/ImportResourceApplication.ts +++ b/packages/server/src/services/Import/ImportResourceApplication.ts @@ -6,6 +6,7 @@ import { ImportFileProcess } from './ImportFileProcess'; import { ImportFilePreview } from './ImportFilePreview'; import { ImportSampleService } from './ImportSample'; import { ImportFileMeta } from './ImportFileMeta'; +import { ImportFileProcessCommit } from './ImportFileProcessCommit'; @Inject() export class ImportResourceApplication { @@ -27,6 +28,9 @@ export class ImportResourceApplication { @Inject() private importMetaService: ImportFileMeta; + @Inject() + private importProcessCommit: ImportFileProcessCommit; + /** * Reads the imported file and stores the import file meta under unqiue id. * @param {number} tenantId - @@ -74,12 +78,12 @@ export class ImportResourceApplication { * @returns {Promise} */ public async process(tenantId: number, importId: number) { - return this.importProcessService.import(tenantId, importId); + return this.importProcessCommit.commit(tenantId, importId); } /** * Retrieves the import meta of the given import id. - * @param {number} tenantId - + * @param {number} tenantId - * @param {string} importId - Import id. * @returns {} */ diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index b254c7113..ba6f28c35 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -647,4 +647,9 @@ export default { onUnexcluding: 'onBankTransactionUnexcluding', onUnexcluded: 'onBankTransactionUnexcluded', }, + + // Import files. + import: { + onImportCommitted: 'onImportFileCommitted', + }, }; diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/components.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/components.tsx index d69196163..2edf0c423 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/components.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/components.tsx @@ -9,7 +9,6 @@ import { PopoverInteractionKind, Position, Tooltip, - MenuDivider, } from '@blueprintjs/core'; import { Box, FormatDateCell, Icon, MaterialProgressBar } from '@/components'; import { useAccountTransactionsContext } from './AccountTransactionsProvider'; @@ -213,9 +212,8 @@ export function useAccountUncategorizedTransactionsColumns() { { id: 'reference_number', Header: 'Ref.#', - accessor: 'reference_number', + accessor: 'reference_no', width: 50, - className: 'reference_number', clickable: true, textOverview: true, }, diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOtherIncome.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOtherIncome.tsx index b45f00bb9..aecf24af3 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOtherIncome.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOtherIncome.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionOtherIncome() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOwnerContribution.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOwnerContribution.tsx index f850f4dc0..5c257ef2b 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOwnerContribution.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionOwnerContribution.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionOwnerContribution() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionTransferFrom.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionTransferFrom.tsx index 01b5b8bba..837b4aaa7 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionTransferFrom.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyIn/CategorizeTransactionTransferFrom.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionTransferFrom() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOtherExpense.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOtherExpense.tsx index 9be2042f2..0071ea99e 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOtherExpense.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOtherExpense.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionOtherExpense() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOwnerDrawings.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOwnerDrawings.tsx index 79746421f..4f5ea024b 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOwnerDrawings.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionOwnerDrawings.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionOwnerDrawings() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionToAccount.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionToAccount.tsx index 93d6b7174..4a13f30ad 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionToAccount.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/MoneyOut/CategorizeTransactionToAccount.tsx @@ -6,6 +6,7 @@ import { FFormGroup, FInputGroup, FTextArea, + Icon, } from '@/components'; import { useCategorizeTransactionBoot } from '../CategorizeTransactionBoot'; import { CategorizeTransactionBranchField } from '../CategorizeTransactionBranchField'; @@ -21,7 +22,7 @@ export default function CategorizeTransactionToAccount() { popoverProps={{ position: Position.BOTTOM, minimal: true }} formatDate={(date) => date.toLocaleDateString()} parseDate={(str) => new Date(str)} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} /> diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.schema.ts b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.schema.ts index 107444d44..35470e6d0 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.schema.ts +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.schema.ts @@ -4,7 +4,7 @@ export const MatchingReconcileFormSchema = Yup.object().shape({ type: Yup.string().required().label('Type'), date: Yup.string().required().label('Date'), amount: Yup.string().required().label('Amount'), - memo: Yup.string().required().label('Memo'), + memo: Yup.string().required().min(3).label('Memo'), referenceNo: Yup.string().label('Refernece #'), category: Yup.string().required().label('Categogry'), }); diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.tsx index 3ae33fd68..7e93aacd6 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingReconcileTransactionAside/MatchingReconcileTransactionForm.tsx @@ -1,14 +1,9 @@ // @ts-nocheck import * as R from 'ramda'; import { Button, Intent, Position, Tag } from '@blueprintjs/core'; -import { - Form, - Formik, - FormikHelpers, - FormikValues, - useFormikContext, -} from 'formik'; +import { Form, Formik, FormikHelpers, useFormikContext } from 'formik'; import moment from 'moment'; +import { round } from 'lodash'; import { AccountsSelect, AppToaster, @@ -19,6 +14,7 @@ import { FInputGroup, FMoneyInputGroup, Group, + Icon, } from '@/components'; import { Aside } from '@/components/Aside/Aside'; import { momentFormatter } from '@/utils'; @@ -100,7 +96,7 @@ function MatchingReconcileTransactionFormRoot({ const _initialValues = { ...initialValues, - amount: Math.abs(reconcileMatchingTransactionPendingAmount) || 0, + amount: round(Math.abs(reconcileMatchingTransactionPendingAmount), 2) || 0, date: moment().format('YYYY-MM-DD'), type: reconcileMatchingTransactionPendingAmount > 0 ? 'deposit' : 'withdrawal', @@ -179,7 +175,7 @@ function CreateReconcileTransactionContent() { }, boundary: 'viewport', }} - inputProps={{ fill: true }} + inputProps={{ fill: true, leftElement: }} fill fastField /> diff --git a/packages/webapp/src/hooks/query/bank-rules.ts b/packages/webapp/src/hooks/query/bank-rules.ts index 7f489f92a..77a770ff4 100644 --- a/packages/webapp/src/hooks/query/bank-rules.ts +++ b/packages/webapp/src/hooks/query/bank-rules.ts @@ -235,6 +235,12 @@ export function useExcludeUncategorizedTransaction( queryClient.invalidateQueries( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); + // Invalidate accounts. + queryClient.invalidateQueries(t.ACCOUNTS); + queryClient.invalidateQueries(t.ACCOUNT); + + // invalidate bank account summary. + queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META); }, ...options, }, @@ -282,6 +288,12 @@ export function useUnexcludeUncategorizedTransaction( queryClient.invalidateQueries( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); + // Invalidate accounts. + queryClient.invalidateQueries(t.ACCOUNTS); + queryClient.invalidateQueries(t.ACCOUNT); + + // Invalidate bank account summary. + queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META); }, ...options, }, @@ -323,6 +335,13 @@ export function useMatchUncategorizedTransaction( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY); + + // Invalidate accounts. + queryClient.invalidateQueries(t.ACCOUNTS); + queryClient.invalidateQueries(t.ACCOUNT); + + // Invalidate bank account summary. + queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META); }, ...props, }); @@ -362,6 +381,13 @@ export function useUnmatchMatchedUncategorizedTransaction( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY); + + // Invalidate accounts. + queryClient.invalidateQueries(t.ACCOUNTS); + queryClient.invalidateQueries(t.ACCOUNT); + + // Invalidate bank account summary. + queryClient.invalidateQueries(QUERY_KEY.BANK_ACCOUNT_SUMMARY_META); }, ...props, }); diff --git a/packages/webapp/src/hooks/query/cashflowAccounts.tsx b/packages/webapp/src/hooks/query/cashflowAccounts.tsx index 656d7cccf..0681210b7 100644 --- a/packages/webapp/src/hooks/query/cashflowAccounts.tsx +++ b/packages/webapp/src/hooks/query/cashflowAccounts.tsx @@ -253,6 +253,9 @@ export function useCategorizeTransaction(props) { queryClient.invalidateQueries( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); + + // Invalidate bank account summary. + queryClient.invalidateQueries('BANK_ACCOUNT_SUMMARY_META'); }, ...props, }, @@ -276,6 +279,9 @@ export function useUncategorizeTransaction(props) { queryClient.invalidateQueries( t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, ); + + // Invalidate bank account summary. + queryClient.invalidateQueries('BANK_ACCOUNT_SUMMARY_META'); }, ...props, },