From c4e69b357712fdee9bb74aaf98f5b5feca62acbd Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Fri, 23 Sep 2022 08:34:08 +0300 Subject: [PATCH] Transactions --- lib/data/models/transaction_model.dart | 31 +++++--- lib/data/models/transaction_model.g.dart | 72 ++++++++++++++----- .../transaction/transaction_selectors.dart | 13 +++- lib/ui/transaction/transaction_list_vm.dart | 1 + lib/ui/transaction/transaction_presenter.dart | 35 ++++++--- lib/ui/transaction/transaction_screen_vm.dart | 1 + lib/utils/i18n.dart | 5 ++ 7 files changed, 116 insertions(+), 42 deletions(-) diff --git a/lib/data/models/transaction_model.dart b/lib/data/models/transaction_model.dart index 02886e489..e2bd36b43 100644 --- a/lib/data/models/transaction_model.dart +++ b/lib/data/models/transaction_model.dart @@ -60,6 +60,7 @@ class TransactionFields { static const String expenseId = 'expense_id'; static const String expense = 'expense'; static const String status = 'status'; + static const String accountType = 'account_type'; } abstract class TransactionEntity extends Object @@ -86,6 +87,8 @@ abstract class TransactionEntity extends Object statusId: '', baseType: TYPE_DEPOSIT, transactionId: 0, + accountType: '', + categoryId: '', ); } @@ -109,6 +112,9 @@ abstract class TransactionEntity extends Object @BuiltValueField(wireName: 'base_type') String get baseType; + @BuiltValueField(wireName: 'account_type') + String get accountType; + String get date; @BuiltValueField(wireName: 'bank_integration_id') @@ -119,8 +125,8 @@ abstract class TransactionEntity extends Object @BuiltValueField(wireName: 'status_id') String get statusId; - //@BuiltValueField(wireName: 'ninja_category_id') - //String get categoryId; + @BuiltValueField(wireName: 'ninja_category_id') + String get categoryId; @BuiltValueField(wireName: 'invoice_ids') String get invoiceIds; @@ -131,9 +137,6 @@ abstract class TransactionEntity extends Object @BuiltValueField(wireName: 'transaction_id') int get transactionId; - //@BuiltValueField(wireName: 'is_matched') - //bool get isMached; - @override EntityType get entityType => EntityType.transaction; @@ -173,6 +176,7 @@ abstract class TransactionEntity extends Object bool sortAscending, BuiltMap invoiceMap, BuiltMap expenseMap, + BuiltMap expenseCategoryMap, BuiltMap bankAccountMap, ) { int response = 0; @@ -193,14 +197,12 @@ abstract class TransactionEntity extends Object case TransactionFields.status: response = transactionA.statusId.compareTo(transactionB.statusId); break; - case TransactionFields.category: - response = transactionA.category - .toLowerCase() - .compareTo(transactionB.category.toLowerCase()); - break; case TransactionFields.date: response = transactionA.date.compareTo(transactionB.date); break; + case TransactionFields.accountType: + response = transactionA.accountType.compareTo(transactionB.accountType); + break; case TransactionFields.invoices: final invoiceA = invoiceMap[transactionA.firstInvoiceId] ?? InvoiceEntity(); @@ -217,6 +219,15 @@ abstract class TransactionEntity extends Object .toLowerCase() .compareTo(expenseB.listDisplayName.toLowerCase()); break; + case TransactionFields.category: + final categoryA = expenseCategoryMap[transactionA.categoryId] ?? + ExpenseCategoryEntity(); + final categoryB = expenseCategoryMap[transactionB.categoryId] ?? + ExpenseCategoryEntity(); + response = categoryA.listDisplayName + .toLowerCase() + .compareTo(categoryB.listDisplayName.toLowerCase()); + break; case TransactionFields.bankAccount: final bankAccountA = bankAccountMap[transactionA.bankAccountId] ?? BankAccountEntity(); diff --git a/lib/data/models/transaction_model.g.dart b/lib/data/models/transaction_model.g.dart index 3da710b46..9c8f2c2b5 100644 --- a/lib/data/models/transaction_model.g.dart +++ b/lib/data/models/transaction_model.g.dart @@ -134,6 +134,9 @@ class _$TransactionEntitySerializer 'base_type', serializers.serialize(object.baseType, specifiedType: const FullType(String)), + 'account_type', + serializers.serialize(object.accountType, + specifiedType: const FullType(String)), 'date', serializers.serialize(object.date, specifiedType: const FullType(String)), 'bank_integration_id', @@ -145,6 +148,9 @@ class _$TransactionEntitySerializer 'status_id', serializers.serialize(object.statusId, specifiedType: const FullType(String)), + 'ninja_category_id', + serializers.serialize(object.categoryId, + specifiedType: const FullType(String)), 'invoice_ids', serializers.serialize(object.invoiceIds, specifiedType: const FullType(String)), @@ -226,6 +232,10 @@ class _$TransactionEntitySerializer result.baseType = serializers.deserialize(value, specifiedType: const FullType(String)) as String; break; + case 'account_type': + result.accountType = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; case 'date': result.date = serializers.deserialize(value, specifiedType: const FullType(String)) as String; @@ -242,6 +252,10 @@ class _$TransactionEntitySerializer result.statusId = serializers.deserialize(value, specifiedType: const FullType(String)) as String; break; + case 'ninja_category_id': + result.categoryId = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; case 'invoice_ids': result.invoiceIds = serializers.deserialize(value, specifiedType: const FullType(String)) as String; @@ -544,6 +558,8 @@ class _$TransactionEntity extends TransactionEntity { @override final String baseType; @override + final String accountType; + @override final String date; @override final String bankAccountId; @@ -552,6 +568,8 @@ class _$TransactionEntity extends TransactionEntity { @override final String statusId; @override + final String categoryId; + @override final String invoiceIds; @override final String expenseId; @@ -583,10 +601,12 @@ class _$TransactionEntity extends TransactionEntity { this.currencyId, this.category, this.baseType, + this.accountType, this.date, this.bankAccountId, this.description, this.statusId, + this.categoryId, this.invoiceIds, this.expenseId, this.transactionId, @@ -607,6 +627,8 @@ class _$TransactionEntity extends TransactionEntity { category, 'TransactionEntity', 'category'); BuiltValueNullFieldError.checkNotNull( baseType, 'TransactionEntity', 'baseType'); + BuiltValueNullFieldError.checkNotNull( + accountType, 'TransactionEntity', 'accountType'); BuiltValueNullFieldError.checkNotNull(date, 'TransactionEntity', 'date'); BuiltValueNullFieldError.checkNotNull( bankAccountId, 'TransactionEntity', 'bankAccountId'); @@ -614,6 +636,8 @@ class _$TransactionEntity extends TransactionEntity { description, 'TransactionEntity', 'description'); BuiltValueNullFieldError.checkNotNull( statusId, 'TransactionEntity', 'statusId'); + BuiltValueNullFieldError.checkNotNull( + categoryId, 'TransactionEntity', 'categoryId'); BuiltValueNullFieldError.checkNotNull( invoiceIds, 'TransactionEntity', 'invoiceIds'); BuiltValueNullFieldError.checkNotNull( @@ -645,10 +669,12 @@ class _$TransactionEntity extends TransactionEntity { currencyId == other.currencyId && category == other.category && baseType == other.baseType && + accountType == other.accountType && date == other.date && bankAccountId == other.bankAccountId && description == other.description && statusId == other.statusId && + categoryId == other.categoryId && invoiceIds == other.invoiceIds && expenseId == other.expenseId && transactionId == other.transactionId && @@ -683,21 +709,15 @@ class _$TransactionEntity extends TransactionEntity { $jc( $jc( $jc( - $jc( - 0, - amount - .hashCode), - currencyId - .hashCode), - category - .hashCode), - baseType - .hashCode), - date.hashCode), - bankAccountId - .hashCode), - description.hashCode), - statusId.hashCode), + $jc($jc($jc(0, amount.hashCode), currencyId.hashCode), + category.hashCode), + baseType.hashCode), + accountType.hashCode), + date.hashCode), + bankAccountId.hashCode), + description.hashCode), + statusId.hashCode), + categoryId.hashCode), invoiceIds.hashCode), expenseId.hashCode), transactionId.hashCode), @@ -718,10 +738,12 @@ class _$TransactionEntity extends TransactionEntity { ..add('currencyId', currencyId) ..add('category', category) ..add('baseType', baseType) + ..add('accountType', accountType) ..add('date', date) ..add('bankAccountId', bankAccountId) ..add('description', description) ..add('statusId', statusId) + ..add('categoryId', categoryId) ..add('invoiceIds', invoiceIds) ..add('expenseId', expenseId) ..add('transactionId', transactionId) @@ -757,6 +779,10 @@ class TransactionEntityBuilder String get baseType => _$this._baseType; set baseType(String baseType) => _$this._baseType = baseType; + String _accountType; + String get accountType => _$this._accountType; + set accountType(String accountType) => _$this._accountType = accountType; + String _date; String get date => _$this._date; set date(String date) => _$this._date = date; @@ -774,6 +800,10 @@ class TransactionEntityBuilder String get statusId => _$this._statusId; set statusId(String statusId) => _$this._statusId = statusId; + String _categoryId; + String get categoryId => _$this._categoryId; + set categoryId(String categoryId) => _$this._categoryId = categoryId; + String _invoiceIds; String get invoiceIds => _$this._invoiceIds; set invoiceIds(String invoiceIds) => _$this._invoiceIds = invoiceIds; @@ -831,10 +861,12 @@ class TransactionEntityBuilder _currencyId = $v.currencyId; _category = $v.category; _baseType = $v.baseType; + _accountType = $v.accountType; _date = $v.date; _bankAccountId = $v.bankAccountId; _description = $v.description; _statusId = $v.statusId; + _categoryId = $v.categoryId; _invoiceIds = $v.invoiceIds; _expenseId = $v.expenseId; _transactionId = $v.transactionId; @@ -874,16 +906,18 @@ class TransactionEntityBuilder category, 'TransactionEntity', 'category'), baseType: BuiltValueNullFieldError.checkNotNull( baseType, 'TransactionEntity', 'baseType'), + accountType: BuiltValueNullFieldError.checkNotNull( + accountType, 'TransactionEntity', 'accountType'), date: BuiltValueNullFieldError.checkNotNull( date, 'TransactionEntity', 'date'), bankAccountId: BuiltValueNullFieldError.checkNotNull( bankAccountId, 'TransactionEntity', 'bankAccountId'), description: BuiltValueNullFieldError.checkNotNull( description, 'TransactionEntity', 'description'), - statusId: BuiltValueNullFieldError.checkNotNull( - statusId, 'TransactionEntity', 'statusId'), - invoiceIds: BuiltValueNullFieldError.checkNotNull( - invoiceIds, 'TransactionEntity', 'invoiceIds'), + statusId: + BuiltValueNullFieldError.checkNotNull(statusId, 'TransactionEntity', 'statusId'), + categoryId: BuiltValueNullFieldError.checkNotNull(categoryId, 'TransactionEntity', 'categoryId'), + invoiceIds: BuiltValueNullFieldError.checkNotNull(invoiceIds, 'TransactionEntity', 'invoiceIds'), expenseId: BuiltValueNullFieldError.checkNotNull(expenseId, 'TransactionEntity', 'expenseId'), transactionId: BuiltValueNullFieldError.checkNotNull(transactionId, 'TransactionEntity', 'transactionId'), isChanged: isChanged, diff --git a/lib/redux/transaction/transaction_selectors.dart b/lib/redux/transaction/transaction_selectors.dart index 74c1ca5fd..69103ec78 100644 --- a/lib/redux/transaction/transaction_selectors.dart +++ b/lib/redux/transaction/transaction_selectors.dart @@ -5,13 +5,14 @@ import 'package:built_collection/built_collection.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; -var memoizedDropdownTransactionList = memo8( +var memoizedDropdownTransactionList = memo9( (BuiltMap transactionMap, BuiltList transactionList, StaticState staticState, BuiltMap userMap, BuiltMap invoiceMap, BuiltMap expenseMap, + BuiltMap expenseCategoryMap, BuiltMap bankAccountMap, String clientId) => dropdownTransactionsSelector( @@ -21,6 +22,7 @@ var memoizedDropdownTransactionList = memo8( userMap, invoiceMap, expenseMap, + expenseCategoryMap, bankAccountMap, clientId)); @@ -31,6 +33,7 @@ List dropdownTransactionsSelector( BuiltMap userMap, BuiltMap invoiceMap, BuiltMap expenseMap, + BuiltMap expenseCategoryMap, BuiltMap bankAccountMap, String clientId) { final list = transactionList.where((transactionId) { @@ -47,17 +50,18 @@ List dropdownTransactionsSelector( final transactionA = transactionMap[transactionAId]; final transactionB = transactionMap[transactionBId]; return transactionA.compareTo(transactionB, TransactionFields.date, true, - invoiceMap, expenseMap, bankAccountMap); + invoiceMap, expenseMap, expenseCategoryMap, bankAccountMap); }); return list; } -var memoizedFilteredTransactionList = memo7((SelectionState selectionState, +var memoizedFilteredTransactionList = memo8((SelectionState selectionState, BuiltMap transactionMap, BuiltList transactionList, BuiltMap invoiceMap, BuiltMap expenseMap, + BuiltMap expenseCategoryMap, BuiltMap bankAccountMap, ListUIState transactionListState) => filteredTransactionsSelector( @@ -66,6 +70,7 @@ var memoizedFilteredTransactionList = memo7((SelectionState selectionState, transactionList, invoiceMap, expenseMap, + expenseCategoryMap, bankAccountMap, transactionListState)); @@ -75,6 +80,7 @@ List filteredTransactionsSelector( BuiltList transactionList, BuiltMap invoiceMap, BuiltMap expenseMap, + BuiltMap expenseCategoryMap, BuiltMap bankAccountMap, ListUIState transactionListState) { final filterEntityId = selectionState.filterEntityId; @@ -108,6 +114,7 @@ List filteredTransactionsSelector( transactionListState.sortAscending, invoiceMap, expenseMap, + expenseCategoryMap, bankAccountMap); }); diff --git a/lib/ui/transaction/transaction_list_vm.dart b/lib/ui/transaction/transaction_list_vm.dart index 056b18b2c..5f9245c20 100644 --- a/lib/ui/transaction/transaction_list_vm.dart +++ b/lib/ui/transaction/transaction_list_vm.dart @@ -92,6 +92,7 @@ class TransactionListVM { state.transactionState.list, state.invoiceState.map, state.expenseState.map, + state.expenseCategoryState.map, state.bankAccountState.map, state.transactionListState), transactionMap: state.transactionState.map, diff --git a/lib/ui/transaction/transaction_presenter.dart b/lib/ui/transaction/transaction_presenter.dart index 361cd7736..f6896d12a 100644 --- a/lib/ui/transaction/transaction_presenter.dart +++ b/lib/ui/transaction/transaction_presenter.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_status_chip.dart'; @@ -26,6 +27,7 @@ class TransactionPresenter extends EntityPresenter { return [ ...getDefaultTableFields(userCompany), ...EntityPresenter.getBaseFields(), + TransactionFields.accountType, TransactionFields.bankAccount, TransactionFields.currency, TransactionFields.amount, @@ -66,25 +68,38 @@ class TransactionPresenter extends EntityPresenter { child: Text(formatNumber(transaction.amount, context, currencyId: transaction.currencyId)), ); - case TransactionFields.category: - return Text(toTitleCase(transaction.category.toLowerCase())); case TransactionFields.description: return Text(transaction.description); + case TransactionFields.accountType: + return Text(toTitleCase(transaction.accountType)); case TransactionFields.bankAccount: final bankAccount = state.bankAccountState.get(transaction.bankAccountId); return LinkTextRelatedEntity( entity: bankAccount, relation: transaction); case TransactionFields.invoices: - return Text(transaction.invoiceIds); - //final invoice = state.invoiceState.get(transaction.invoiceIds); - //return LinkTextRelatedEntity(entity: invoice, relation: transaction); + return ConstrainedBox( + constraints: BoxConstraints(maxWidth: kTableColumnWidthMax), + child: Wrap( + clipBehavior: Clip.antiAlias, + children: transaction.invoiceIds + .split(',') + .map((invoiceId) => state.invoiceState.map[invoiceId]) + .where((invoice) => invoice != null) + .map((invoice) => Padding( + padding: const EdgeInsets.only(right: 8), + child: LinkTextRelatedEntity( + entity: invoice, relation: transaction), + )) + .toList(), + ), + ); case TransactionFields.expense: - return Text(transaction.expenseId); - //final expense = state.expenseState.get(transaction.expenseId); - //return LinkTextRelatedEntity(entity: expense, relation: transaction); - case TransactionFields.currency: - return Text(state.bankAccountState.get(transaction.bankAccountId).name); + final expense = state.expenseState.get(transaction.expenseId); + return LinkTextRelatedEntity(entity: expense, relation: transaction); + case TransactionFields.category: + final category = state.expenseCategoryState.get(transaction.categoryId); + return LinkTextRelatedEntity(entity: category, relation: transaction); } return super.getField(field: field, context: context); diff --git a/lib/ui/transaction/transaction_screen_vm.dart b/lib/ui/transaction/transaction_screen_vm.dart index 8473403fb..4fd661724 100644 --- a/lib/ui/transaction/transaction_screen_vm.dart +++ b/lib/ui/transaction/transaction_screen_vm.dart @@ -52,6 +52,7 @@ class TransactionScreenVM { state.transactionState.list, state.invoiceState.map, state.expenseState.map, + state.expenseCategoryState.map, state.bankAccountState.map, state.transactionListState, ), diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 313dfbffb..2752002bd 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -16,6 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'account_type': 'Account Type', 'new_bank_account': 'New Bank Account', 'connect_accounts': 'Connect Accounts', 'manage_rules': 'Manage Rules', @@ -87382,6 +87383,10 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['new_bank_account'] ?? _localizedValues['en']['new_bank_account']; + String get accountType => + _localizedValues[localeCode]['account_type'] ?? + _localizedValues['en']['account_type']; + // STARTER: lang field - do not remove comment String lookup(String key) {