Bank transactions

This commit is contained in:
Hillel Coren 2022-09-14 13:21:41 +03:00
parent 018d7887a8
commit 65d96be8ba
9 changed files with 233 additions and 50 deletions

View File

@ -329,6 +329,7 @@ abstract class CompanyEntity extends Object
@BuiltValueField(wireName: 'bank_integrations') @BuiltValueField(wireName: 'bank_integrations')
BuiltList<BankAccountEntity> get bankAccounts; BuiltList<BankAccountEntity> get bankAccounts;
@BuiltValueField(wireName: 'bank_transactions')
BuiltList<TransactionEntity> get transactions; BuiltList<TransactionEntity> get transactions;
BuiltList<TaskEntity> get tasks; BuiltList<TaskEntity> get tasks;

View File

@ -235,7 +235,7 @@ class _$CompanyEntitySerializer implements StructuredSerializer<CompanyEntity> {
serializers.serialize(object.bankAccounts, serializers.serialize(object.bankAccounts,
specifiedType: const FullType( specifiedType: const FullType(
BuiltList, const [const FullType(BankAccountEntity)])), BuiltList, const [const FullType(BankAccountEntity)])),
'transactions', 'bank_transactions',
serializers.serialize(object.transactions, serializers.serialize(object.transactions,
specifiedType: const FullType( specifiedType: const FullType(
BuiltList, const [const FullType(TransactionEntity)])), BuiltList, const [const FullType(TransactionEntity)])),
@ -679,7 +679,7 @@ class _$CompanyEntitySerializer implements StructuredSerializer<CompanyEntity> {
BuiltList, const [const FullType(BankAccountEntity)])) BuiltList, const [const FullType(BankAccountEntity)]))
as BuiltList<Object>); as BuiltList<Object>);
break; break;
case 'transactions': case 'bank_transactions':
result.transactions.replace(serializers.deserialize(value, result.transactions.replace(serializers.deserialize(value,
specifiedType: const FullType( specifiedType: const FullType(
BuiltList, const [const FullType(TransactionEntity)])) BuiltList, const [const FullType(TransactionEntity)]))

View File

@ -46,7 +46,7 @@ abstract class TransactionItemResponse
class TransactionFields { class TransactionFields {
// STARTER: fields - do not remove comment // STARTER: fields - do not remove comment
static const String reference = 'reference'; static const String description = 'description';
static const String date = 'date'; static const String date = 'date';
} }
@ -63,7 +63,6 @@ abstract class TransactionEntity extends Object
createdUserId: '', createdUserId: '',
assignedUserId: '', assignedUserId: '',
archivedAt: 0, archivedAt: 0,
reference: '',
); );
} }
@ -73,7 +72,29 @@ abstract class TransactionEntity extends Object
@memoized @memoized
int get hashCode; int get hashCode;
String get reference; double get amount;
@BuiltValueField(wireName: 'currency_id')
String get currencyId;
@BuiltValueField(wireName: 'category_type')
String get category;
String get date;
@BuiltValueField(wireName: 'bank_integration_id')
String get bankAccountId;
String get description;
@BuiltValueField(wireName: 'invoice_id')
String get invoiceId;
@BuiltValueField(wireName: 'expense_id')
String get expenseId;
//@BuiltValueField(wireName: 'is_matched')
//bool get isMached;
@override @override
EntityType get entityType => EntityType.transaction; EntityType get entityType => EntityType.transaction;
@ -108,10 +129,10 @@ abstract class TransactionEntity extends Object
switch (sortField) { switch (sortField) {
// STARTER: sort switch - do not remove comment // STARTER: sort switch - do not remove comment
case TransactionFields.reference: case TransactionFields.description:
response = transactionA.reference response = transactionA.description
.toLowerCase() .toLowerCase()
.compareTo(transactionB.reference.toLowerCase()); .compareTo(transactionB.description.toLowerCase());
break; break;
default: default:
@ -121,9 +142,9 @@ abstract class TransactionEntity extends Object
if (response == 0) { if (response == 0) {
// STARTER: sort default - do not remove comment // STARTER: sort default - do not remove comment
return transactionA.reference return transactionA.description
.toLowerCase() .toLowerCase()
.compareTo(transactionB.reference.toLowerCase()); .compareTo(transactionB.description.toLowerCase());
} else { } else {
return response; return response;
} }

View File

@ -120,8 +120,28 @@ class _$TransactionEntitySerializer
Iterable<Object> serialize(Serializers serializers, TransactionEntity object, Iterable<Object> serialize(Serializers serializers, TransactionEntity object,
{FullType specifiedType = FullType.unspecified}) { {FullType specifiedType = FullType.unspecified}) {
final result = <Object>[ final result = <Object>[
'reference', 'amount',
serializers.serialize(object.reference, serializers.serialize(object.amount,
specifiedType: const FullType(double)),
'currency_id',
serializers.serialize(object.currencyId,
specifiedType: const FullType(String)),
'category_type',
serializers.serialize(object.category,
specifiedType: const FullType(String)),
'date',
serializers.serialize(object.date, specifiedType: const FullType(String)),
'bank_integration_id',
serializers.serialize(object.bankAccountId,
specifiedType: const FullType(String)),
'description',
serializers.serialize(object.description,
specifiedType: const FullType(String)),
'invoice_id',
serializers.serialize(object.invoiceId,
specifiedType: const FullType(String)),
'expense_id',
serializers.serialize(object.expenseId,
specifiedType: const FullType(String)), specifiedType: const FullType(String)),
'created_at', 'created_at',
serializers.serialize(object.createdAt, serializers.serialize(object.createdAt,
@ -179,8 +199,36 @@ class _$TransactionEntitySerializer
iterator.moveNext(); iterator.moveNext();
final Object value = iterator.current; final Object value = iterator.current;
switch (key) { switch (key) {
case 'reference': case 'amount':
result.reference = serializers.deserialize(value, result.amount = serializers.deserialize(value,
specifiedType: const FullType(double)) as double;
break;
case 'currency_id':
result.currencyId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'category_type':
result.category = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'date':
result.date = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'bank_integration_id':
result.bankAccountId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'description':
result.description = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'invoice_id':
result.invoiceId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'expense_id':
result.expenseId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String; specifiedType: const FullType(String)) as String;
break; break;
case 'isChanged': case 'isChanged':
@ -414,7 +462,21 @@ class TransactionItemResponseBuilder
class _$TransactionEntity extends TransactionEntity { class _$TransactionEntity extends TransactionEntity {
@override @override
final String reference; final double amount;
@override
final String currencyId;
@override
final String category;
@override
final String date;
@override
final String bankAccountId;
@override
final String description;
@override
final String invoiceId;
@override
final String expenseId;
@override @override
final bool isChanged; final bool isChanged;
@override @override
@ -437,7 +499,14 @@ class _$TransactionEntity extends TransactionEntity {
(new TransactionEntityBuilder()..update(updates)).build(); (new TransactionEntityBuilder()..update(updates)).build();
_$TransactionEntity._( _$TransactionEntity._(
{this.reference, {this.amount,
this.currencyId,
this.category,
this.date,
this.bankAccountId,
this.description,
this.invoiceId,
this.expenseId,
this.isChanged, this.isChanged,
this.createdAt, this.createdAt,
this.updatedAt, this.updatedAt,
@ -448,7 +517,20 @@ class _$TransactionEntity extends TransactionEntity {
this.id}) this.id})
: super._() { : super._() {
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
reference, 'TransactionEntity', 'reference'); amount, 'TransactionEntity', 'amount');
BuiltValueNullFieldError.checkNotNull(
currencyId, 'TransactionEntity', 'currencyId');
BuiltValueNullFieldError.checkNotNull(
category, 'TransactionEntity', 'category');
BuiltValueNullFieldError.checkNotNull(date, 'TransactionEntity', 'date');
BuiltValueNullFieldError.checkNotNull(
bankAccountId, 'TransactionEntity', 'bankAccountId');
BuiltValueNullFieldError.checkNotNull(
description, 'TransactionEntity', 'description');
BuiltValueNullFieldError.checkNotNull(
invoiceId, 'TransactionEntity', 'invoiceId');
BuiltValueNullFieldError.checkNotNull(
expenseId, 'TransactionEntity', 'expenseId');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
createdAt, 'TransactionEntity', 'createdAt'); createdAt, 'TransactionEntity', 'createdAt');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
@ -470,7 +552,14 @@ class _$TransactionEntity extends TransactionEntity {
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(other, this)) return true; if (identical(other, this)) return true;
return other is TransactionEntity && return other is TransactionEntity &&
reference == other.reference && amount == other.amount &&
currencyId == other.currencyId &&
category == other.category &&
date == other.date &&
bankAccountId == other.bankAccountId &&
description == other.description &&
invoiceId == other.invoiceId &&
expenseId == other.expenseId &&
isChanged == other.isChanged && isChanged == other.isChanged &&
createdAt == other.createdAt && createdAt == other.createdAt &&
updatedAt == other.updatedAt && updatedAt == other.updatedAt &&
@ -491,7 +580,26 @@ class _$TransactionEntity extends TransactionEntity {
$jc( $jc(
$jc( $jc(
$jc( $jc(
$jc($jc(0, reference.hashCode), $jc(
$jc(
$jc(
$jc(
$jc(
$jc(
$jc(
$jc(
$jc(
0,
amount
.hashCode),
currencyId
.hashCode),
category.hashCode),
date.hashCode),
bankAccountId.hashCode),
description.hashCode),
invoiceId.hashCode),
expenseId.hashCode),
isChanged.hashCode), isChanged.hashCode),
createdAt.hashCode), createdAt.hashCode),
updatedAt.hashCode), updatedAt.hashCode),
@ -505,7 +613,14 @@ class _$TransactionEntity extends TransactionEntity {
@override @override
String toString() { String toString() {
return (newBuiltValueToStringHelper('TransactionEntity') return (newBuiltValueToStringHelper('TransactionEntity')
..add('reference', reference) ..add('amount', amount)
..add('currencyId', currencyId)
..add('category', category)
..add('date', date)
..add('bankAccountId', bankAccountId)
..add('description', description)
..add('invoiceId', invoiceId)
..add('expenseId', expenseId)
..add('isChanged', isChanged) ..add('isChanged', isChanged)
..add('createdAt', createdAt) ..add('createdAt', createdAt)
..add('updatedAt', updatedAt) ..add('updatedAt', updatedAt)
@ -522,9 +637,38 @@ class TransactionEntityBuilder
implements Builder<TransactionEntity, TransactionEntityBuilder> { implements Builder<TransactionEntity, TransactionEntityBuilder> {
_$TransactionEntity _$v; _$TransactionEntity _$v;
String _reference; double _amount;
String get reference => _$this._reference; double get amount => _$this._amount;
set reference(String reference) => _$this._reference = reference; set amount(double amount) => _$this._amount = amount;
String _currencyId;
String get currencyId => _$this._currencyId;
set currencyId(String currencyId) => _$this._currencyId = currencyId;
String _category;
String get category => _$this._category;
set category(String category) => _$this._category = category;
String _date;
String get date => _$this._date;
set date(String date) => _$this._date = date;
String _bankAccountId;
String get bankAccountId => _$this._bankAccountId;
set bankAccountId(String bankAccountId) =>
_$this._bankAccountId = bankAccountId;
String _description;
String get description => _$this._description;
set description(String description) => _$this._description = description;
String _invoiceId;
String get invoiceId => _$this._invoiceId;
set invoiceId(String invoiceId) => _$this._invoiceId = invoiceId;
String _expenseId;
String get expenseId => _$this._expenseId;
set expenseId(String expenseId) => _$this._expenseId = expenseId;
bool _isChanged; bool _isChanged;
bool get isChanged => _$this._isChanged; bool get isChanged => _$this._isChanged;
@ -565,7 +709,14 @@ class TransactionEntityBuilder
TransactionEntityBuilder get _$this { TransactionEntityBuilder get _$this {
final $v = _$v; final $v = _$v;
if ($v != null) { if ($v != null) {
_reference = $v.reference; _amount = $v.amount;
_currencyId = $v.currencyId;
_category = $v.category;
_date = $v.date;
_bankAccountId = $v.bankAccountId;
_description = $v.description;
_invoiceId = $v.invoiceId;
_expenseId = $v.expenseId;
_isChanged = $v.isChanged; _isChanged = $v.isChanged;
_createdAt = $v.createdAt; _createdAt = $v.createdAt;
_updatedAt = $v.updatedAt; _updatedAt = $v.updatedAt;
@ -594,20 +745,31 @@ class TransactionEntityBuilder
_$TransactionEntity build() { _$TransactionEntity build() {
final _$result = _$v ?? final _$result = _$v ??
new _$TransactionEntity._( new _$TransactionEntity._(
reference: BuiltValueNullFieldError.checkNotNull( amount: BuiltValueNullFieldError.checkNotNull(
reference, 'TransactionEntity', 'reference'), amount, 'TransactionEntity', 'amount'),
currencyId: BuiltValueNullFieldError.checkNotNull(
currencyId, 'TransactionEntity', 'currencyId'),
category: BuiltValueNullFieldError.checkNotNull(
category, 'TransactionEntity', 'category'),
date: BuiltValueNullFieldError.checkNotNull(
date, 'TransactionEntity', 'date'),
bankAccountId: BuiltValueNullFieldError.checkNotNull(
bankAccountId, 'TransactionEntity', 'bankAccountId'),
description: BuiltValueNullFieldError.checkNotNull(
description, 'TransactionEntity', 'description'),
invoiceId: BuiltValueNullFieldError.checkNotNull(
invoiceId, 'TransactionEntity', 'invoiceId'),
expenseId: BuiltValueNullFieldError.checkNotNull(
expenseId, 'TransactionEntity', 'expenseId'),
isChanged: isChanged, isChanged: isChanged,
createdAt: BuiltValueNullFieldError.checkNotNull( createdAt:
createdAt, 'TransactionEntity', 'createdAt'), BuiltValueNullFieldError.checkNotNull(createdAt, 'TransactionEntity', 'createdAt'),
updatedAt: BuiltValueNullFieldError.checkNotNull( updatedAt: BuiltValueNullFieldError.checkNotNull(updatedAt, 'TransactionEntity', 'updatedAt'),
updatedAt, 'TransactionEntity', 'updatedAt'), archivedAt: BuiltValueNullFieldError.checkNotNull(archivedAt, 'TransactionEntity', 'archivedAt'),
archivedAt: BuiltValueNullFieldError.checkNotNull(
archivedAt, 'TransactionEntity', 'archivedAt'),
isDeleted: isDeleted, isDeleted: isDeleted,
createdUserId: createdUserId, createdUserId: createdUserId,
assignedUserId: assignedUserId, assignedUserId: assignedUserId,
id: BuiltValueNullFieldError.checkNotNull( id: BuiltValueNullFieldError.checkNotNull(id, 'TransactionEntity', 'id'));
id, 'TransactionEntity', 'id'));
replace(_$result); replace(_$result);
return _$result; return _$result;
} }

View File

@ -33,8 +33,7 @@ List<String> dropdownTransactionsSelector(
list.sort((transactionAId, transactionBId) { list.sort((transactionAId, transactionBId) {
final transactionA = transactionMap[transactionAId]; final transactionA = transactionMap[transactionAId];
final transactionB = transactionMap[transactionBId]; final transactionB = transactionMap[transactionBId];
return transactionA.compareTo( return transactionA.compareTo(transactionB, TransactionFields.date, true);
transactionB, TransactionFields.reference, true);
}); });
return list; return list;

View File

@ -605,6 +605,13 @@ class _MenuDrawerState extends State<MenuDrawer> {
icon: getEntityIcon(EntityType.purchaseOrder), icon: getEntityIcon(EntityType.purchaseOrder),
title: localization.purchaseOrders, title: localization.purchaseOrders,
), ),
if (supportsBankAccounts())
DrawerTile(
company: company,
entityType: EntityType.transaction,
icon: getEntityIcon(EntityType.transaction),
title: localization.transactions,
),
DrawerTile( DrawerTile(
company: company, company: company,
entityType: EntityType.expense, entityType: EntityType.expense,
@ -613,13 +620,6 @@ class _MenuDrawerState extends State<MenuDrawer> {
iconTooltip: localization.newExpense, iconTooltip: localization.newExpense,
), ),
// STARTER: menu - do not remove comment // STARTER: menu - do not remove comment
DrawerTile(
company: company,
entityType: EntityType.transaction,
icon: getEntityIcon(EntityType.transaction),
title: localization.transactions,
),
DrawerTile( DrawerTile(
company: company, company: company,
entityType: EntityType.recurringExpense, entityType: EntityType.recurringExpense,

View File

@ -24,7 +24,7 @@ class _TransactionEditState extends State<TransactionEdit> {
final _debouncer = Debouncer(); final _debouncer = Debouncer();
// STARTER: controllers - do not remove comment // STARTER: controllers - do not remove comment
final _referenceController = TextEditingController(); final _descriptionController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
@ -32,14 +32,14 @@ class _TransactionEditState extends State<TransactionEdit> {
void didChangeDependencies() { void didChangeDependencies() {
_controllers = [ _controllers = [
// STARTER: array - do not remove comment // STARTER: array - do not remove comment
_referenceController, _descriptionController,
]; ];
_controllers.forEach((controller) => controller.removeListener(_onChanged)); _controllers.forEach((controller) => controller.removeListener(_onChanged));
final transaction = widget.viewModel.transaction; final transaction = widget.viewModel.transaction;
// STARTER: read value - do not remove comment // STARTER: read value - do not remove comment
_referenceController.text = transaction.reference; _descriptionController.text = transaction.description;
_controllers.forEach((controller) => controller.addListener(_onChanged)); _controllers.forEach((controller) => controller.addListener(_onChanged));
@ -60,7 +60,7 @@ class _TransactionEditState extends State<TransactionEdit> {
_debouncer.run(() { _debouncer.run(() {
final transaction = widget.viewModel.transaction.rebuild((b) => b final transaction = widget.viewModel.transaction.rebuild((b) => b
// STARTER: set value - do not remove comment // STARTER: set value - do not remove comment
..reference = _referenceController.text.trim()); ..description = _descriptionController.text.trim());
if (transaction != widget.viewModel.transaction) { if (transaction != widget.viewModel.transaction) {
widget.viewModel.onChanged(transaction); widget.viewModel.onChanged(transaction);
} }
@ -102,7 +102,7 @@ class _TransactionEditState extends State<TransactionEdit> {
children: <Widget>[ children: <Widget>[
// STARTER: widgets - do not remove comment // STARTER: widgets - do not remove comment
TextFormField( TextFormField(
controller: _referenceController, controller: _descriptionController,
autocorrect: false, autocorrect: false,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Transactions', labelText: 'Transactions',

View File

@ -71,7 +71,7 @@ class TransactionListItem extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: Text( child: Text(
transaction.reference, transaction.description,
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
), ),
), ),

View File

@ -64,7 +64,7 @@ class TransactionScreen extends StatelessWidget {
}, },
sortFields: [ sortFields: [
TransactionFields.date, TransactionFields.date,
TransactionFields.reference, TransactionFields.description,
], ],
onSelectedState: (EntityState state, value) { onSelectedState: (EntityState state, value) {
store.dispatch(FilterTransactionsByState(state)); store.dispatch(FilterTransactionsByState(state));