Transaction rules

This commit is contained in:
Hillel Coren 2022-11-22 15:41:05 +02:00
parent 3c5be1884a
commit c10bc4116d
5 changed files with 173 additions and 34 deletions

View File

@ -196,6 +196,7 @@ Serializers _$serializers = (new Serializers().toBuilder()
..add(TransactionEntity.serializer)
..add(TransactionItemResponse.serializer)
..add(TransactionListResponse.serializer)
..add(TransactionRuleCriteriaEntity.serializer)
..add(TransactionRuleEntity.serializer)
..add(TransactionRuleItemResponse.serializer)
..add(TransactionRuleListResponse.serializer)
@ -572,6 +573,10 @@ Serializers _$serializers = (new Serializers().toBuilder()
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(TransactionEntity)]),
() => new ListBuilder<TransactionEntity>())
..addBuilderFactory(
const FullType(
BuiltList, const [const FullType(TransactionRuleCriteriaEntity)]),
() => new ListBuilder<TransactionRuleCriteriaEntity>())
..addBuilderFactory(
const FullType(
BuiltList, const [const FullType(TransactionRuleEntity)]),

View File

@ -69,6 +69,7 @@ abstract class TransactionRuleEntity extends Object
appliesTo: TransactionEntity.TYPE_WITHDRAWL,
vendorId: '',
categoryId: '',
rules: BuiltList<TransactionRuleCriteriaEntity>(),
);
}
@ -95,6 +96,8 @@ abstract class TransactionRuleEntity extends Object
@BuiltValueField(wireName: 'category_id')
String get categoryId;
BuiltList<TransactionRuleCriteriaEntity> get rules;
@override
EntityType get entityType => EntityType.transactionRule;
@ -196,6 +199,9 @@ abstract class TransactionRuleCriteriaEntity
TransactionRuleCriteriaEntity._();
static const SEARCH_KEY_DESCRIPTION = 'description';
static const SEARCH_KEY_AMOUNT = 'amount';
@override
@memoized
int get hashCode;

View File

@ -146,6 +146,10 @@ class _$TransactionRuleEntitySerializer
'category_id',
serializers.serialize(object.categoryId,
specifiedType: const FullType(String)),
'rules',
serializers.serialize(object.rules,
specifiedType: const FullType(BuiltList,
const [const FullType(TransactionRuleCriteriaEntity)])),
'created_at',
serializers.serialize(object.createdAt,
specifiedType: const FullType(int)),
@ -226,6 +230,12 @@ class _$TransactionRuleEntitySerializer
result.categoryId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'rules':
result.rules.replace(serializers.deserialize(value,
specifiedType: const FullType(BuiltList, const [
const FullType(TransactionRuleCriteriaEntity)
])) as BuiltList<Object>);
break;
case 'isChanged':
result.isChanged = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
@ -531,6 +541,8 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
@override
final String categoryId;
@override
final BuiltList<TransactionRuleCriteriaEntity> rules;
@override
final bool isChanged;
@override
final int createdAt;
@ -558,6 +570,7 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
this.appliesTo,
this.vendorId,
this.categoryId,
this.rules,
this.isChanged,
this.createdAt,
this.updatedAt,
@ -579,6 +592,8 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
vendorId, 'TransactionRuleEntity', 'vendorId');
BuiltValueNullFieldError.checkNotNull(
categoryId, 'TransactionRuleEntity', 'categoryId');
BuiltValueNullFieldError.checkNotNull(
rules, 'TransactionRuleEntity', 'rules');
BuiltValueNullFieldError.checkNotNull(
createdAt, 'TransactionRuleEntity', 'createdAt');
BuiltValueNullFieldError.checkNotNull(
@ -607,6 +622,7 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
appliesTo == other.appliesTo &&
vendorId == other.vendorId &&
categoryId == other.categoryId &&
rules == other.rules &&
isChanged == other.isChanged &&
createdAt == other.createdAt &&
updatedAt == other.updatedAt &&
@ -632,12 +648,17 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
$jc(
$jc(
$jc(
$jc($jc(0, name.hashCode),
matchesOnAll.hashCode),
autoConvert.hashCode),
appliesTo.hashCode),
vendorId.hashCode),
categoryId.hashCode),
$jc(
$jc(
$jc(0,
name.hashCode),
matchesOnAll
.hashCode),
autoConvert.hashCode),
appliesTo.hashCode),
vendorId.hashCode),
categoryId.hashCode),
rules.hashCode),
isChanged.hashCode),
createdAt.hashCode),
updatedAt.hashCode),
@ -657,6 +678,7 @@ class _$TransactionRuleEntity extends TransactionRuleEntity {
..add('appliesTo', appliesTo)
..add('vendorId', vendorId)
..add('categoryId', categoryId)
..add('rules', rules)
..add('isChanged', isChanged)
..add('createdAt', createdAt)
..add('updatedAt', updatedAt)
@ -697,6 +719,12 @@ class TransactionRuleEntityBuilder
String get categoryId => _$this._categoryId;
set categoryId(String categoryId) => _$this._categoryId = categoryId;
ListBuilder<TransactionRuleCriteriaEntity> _rules;
ListBuilder<TransactionRuleCriteriaEntity> get rules =>
_$this._rules ??= new ListBuilder<TransactionRuleCriteriaEntity>();
set rules(ListBuilder<TransactionRuleCriteriaEntity> rules) =>
_$this._rules = rules;
bool _isChanged;
bool get isChanged => _$this._isChanged;
set isChanged(bool isChanged) => _$this._isChanged = isChanged;
@ -742,6 +770,7 @@ class TransactionRuleEntityBuilder
_appliesTo = $v.appliesTo;
_vendorId = $v.vendorId;
_categoryId = $v.categoryId;
_rules = $v.rules.toBuilder();
_isChanged = $v.isChanged;
_createdAt = $v.createdAt;
_updatedAt = $v.updatedAt;
@ -768,30 +797,44 @@ class TransactionRuleEntityBuilder
@override
_$TransactionRuleEntity build() {
final _$result = _$v ??
new _$TransactionRuleEntity._(
name: BuiltValueNullFieldError.checkNotNull(
name, 'TransactionRuleEntity', 'name'),
matchesOnAll: BuiltValueNullFieldError.checkNotNull(
matchesOnAll, 'TransactionRuleEntity', 'matchesOnAll'),
autoConvert: BuiltValueNullFieldError.checkNotNull(
autoConvert, 'TransactionRuleEntity', 'autoConvert'),
appliesTo: BuiltValueNullFieldError.checkNotNull(
appliesTo, 'TransactionRuleEntity', 'appliesTo'),
vendorId: BuiltValueNullFieldError.checkNotNull(
vendorId, 'TransactionRuleEntity', 'vendorId'),
categoryId: BuiltValueNullFieldError.checkNotNull(
categoryId, 'TransactionRuleEntity', 'categoryId'),
isChanged: isChanged,
createdAt: BuiltValueNullFieldError.checkNotNull(
createdAt, 'TransactionRuleEntity', 'createdAt'),
updatedAt: BuiltValueNullFieldError.checkNotNull(
updatedAt, 'TransactionRuleEntity', 'updatedAt'),
archivedAt: BuiltValueNullFieldError.checkNotNull(archivedAt, 'TransactionRuleEntity', 'archivedAt'),
isDeleted: isDeleted,
createdUserId: createdUserId,
assignedUserId: assignedUserId,
id: BuiltValueNullFieldError.checkNotNull(id, 'TransactionRuleEntity', 'id'));
_$TransactionRuleEntity _$result;
try {
_$result = _$v ??
new _$TransactionRuleEntity._(
name: BuiltValueNullFieldError.checkNotNull(
name, 'TransactionRuleEntity', 'name'),
matchesOnAll: BuiltValueNullFieldError.checkNotNull(
matchesOnAll, 'TransactionRuleEntity', 'matchesOnAll'),
autoConvert: BuiltValueNullFieldError.checkNotNull(
autoConvert, 'TransactionRuleEntity', 'autoConvert'),
appliesTo: BuiltValueNullFieldError.checkNotNull(
appliesTo, 'TransactionRuleEntity', 'appliesTo'),
vendorId: BuiltValueNullFieldError.checkNotNull(
vendorId, 'TransactionRuleEntity', 'vendorId'),
categoryId: BuiltValueNullFieldError.checkNotNull(
categoryId, 'TransactionRuleEntity', 'categoryId'),
rules: rules.build(),
isChanged: isChanged,
createdAt: BuiltValueNullFieldError.checkNotNull(
createdAt, 'TransactionRuleEntity', 'createdAt'),
updatedAt: BuiltValueNullFieldError.checkNotNull(
updatedAt, 'TransactionRuleEntity', 'updatedAt'),
archivedAt: BuiltValueNullFieldError.checkNotNull(archivedAt, 'TransactionRuleEntity', 'archivedAt'),
isDeleted: isDeleted,
createdUserId: createdUserId,
assignedUserId: assignedUserId,
id: BuiltValueNullFieldError.checkNotNull(id, 'TransactionRuleEntity', 'id'));
} catch (_) {
String _$failedField;
try {
_$failedField = 'rules';
rules.build();
} catch (e) {
throw new BuiltValueNestedFieldError(
'TransactionRuleEntity', _$failedField, e.toString());
}
rethrow;
}
replace(_$result);
return _$result;
}

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/expense_category_model.dart';
import 'package:invoiceninja_flutter/data/models/transaction_rule_model.dart';
import 'package:invoiceninja_flutter/data/models/vendor_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/expense_category/expense_category_actions.dart';
@ -11,7 +12,9 @@ import 'package:invoiceninja_flutter/redux/vendor/vendor_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.dart';
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
import 'package:invoiceninja_flutter/ui/app/icon_text.dart';
import 'package:invoiceninja_flutter/ui/transaction_rule/edit/transaction_rule_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
@ -99,8 +102,9 @@ class _TransactionRuleEditState extends State<TransactionRuleEdit> {
onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) => _onSubmitted(),
body: Form(
key: _formKey,
child: Builder(builder: (BuildContext context) {
key: _formKey,
child: Builder(
builder: (BuildContext context) {
return ScrollableListView(
children: <Widget>[
FormCard(
@ -111,7 +115,7 @@ class _TransactionRuleEditState extends State<TransactionRuleEdit> {
controller: _nameController,
onSavePressed: (context) => _onSubmitted(),
),
SizedBox(height: 12),
SizedBox(height: 16),
SwitchListTile(
title: Text(localization.matchAllRules),
subtitle: Text(localization.matchAllRulesHelp),
@ -134,6 +138,25 @@ class _TransactionRuleEditState extends State<TransactionRuleEdit> {
),
],
),
FormCard(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
OutlinedButton(
onPressed: () {
showDialog<TransactionRuleCriteriaEntity>(
context: context,
builder: (context) => _RuleCriteria());
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: IconText(
text: localization.addRule,
icon: Icons.add,
),
),
),
],
),
FormCard(
children: [
EntityDropdown(
@ -182,7 +205,64 @@ class _TransactionRuleEditState extends State<TransactionRuleEdit> {
),
],
);
})),
},
),
),
);
}
}
class _RuleCriteria extends StatefulWidget {
const _RuleCriteria({
Key key,
this.criteria,
}) : super(key: key);
final TransactionRuleCriteriaEntity criteria;
@override
State<_RuleCriteria> createState() => __RuleCriteriaState();
}
class __RuleCriteriaState extends State<_RuleCriteria> {
TransactionRuleCriteriaEntity _criteria;
@override
void initState() {
super.initState();
_criteria = widget.criteria ?? TransactionRuleCriteriaEntity();
}
@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context);
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
AppDropdownButton<String>(
labelText: localization.field,
value: _criteria.searchKey,
onChanged: (dynamic value) {
setState(() {
_criteria = _criteria.rebuild((b) => b..searchKey = value);
});
},
items: [
DropdownMenuItem<String>(
child: Text(localization.description),
value: TransactionRuleCriteriaEntity.SEARCH_KEY_DESCRIPTION,
),
DropdownMenuItem<String>(
child: Text(localization.amount),
value: TransactionRuleCriteriaEntity.SEARCH_KEY_AMOUNT,
),
],
),
],
),
);
}
}

View File

@ -16,6 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'add_rule': 'Add Rule',
'match_all_rules': 'Match All Rules',
'match_all_rules_help':
'All criteria needs to match for the rule to be applied',
@ -90529,6 +90530,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['auto_convert_help'] ??
_localizedValues['en']['auto_convert_help'];
String get addRule =>
_localizedValues[localeCode]['add_rule'] ??
_localizedValues['en']['add_rule'];
// STARTER: lang field - do not remove comment
String lookup(String key) {