diff --git a/lib/data/models/expense_model.dart b/lib/data/models/expense_model.dart index e17853542..e6e14bb4c 100644 --- a/lib/data/models/expense_model.dart +++ b/lib/data/models/expense_model.dart @@ -126,7 +126,7 @@ abstract class ExpenseEntity extends Object paymentDate: (company?.markExpensesPaid ?? false) ? convertDateTimeToSqlDate() : '', - paymentTypeId: '', + paymentTypeId: company?.settings?.defaultExpensePaymentTypeId ?? '', exchangeRate: 1, currencyId: (vendor != null && vendor.hasCurrency) ? vendor.currencyId diff --git a/lib/data/models/settings_model.dart b/lib/data/models/settings_model.dart index d9eaa2231..ef9522a55 100644 --- a/lib/data/models/settings_model.dart +++ b/lib/data/models/settings_model.dart @@ -992,6 +992,10 @@ abstract class SettingsEntity @BuiltValueField(wireName: 'e_invoice_type') String get eInvoiceType; + @nullable + @BuiltValueField(wireName: 'default_expense_payment_type_id') + String get defaultExpensePaymentTypeId; + bool get hasAddress => address1 != null && address1.isNotEmpty; bool get hasLogo => companyLogo != null && companyLogo.isNotEmpty; diff --git a/lib/data/models/settings_model.g.dart b/lib/data/models/settings_model.g.dart index f664195db..92ac7061b 100644 --- a/lib/data/models/settings_model.g.dart +++ b/lib/data/models/settings_model.g.dart @@ -1520,6 +1520,13 @@ class _$SettingsEntitySerializer ..add(serializers.serialize(value, specifiedType: const FullType(String))); } + value = object.defaultExpensePaymentTypeId; + if (value != null) { + result + ..add('default_expense_payment_type_id') + ..add(serializers.serialize(value, + specifiedType: const FullType(String))); + } return result; } @@ -2404,6 +2411,10 @@ class _$SettingsEntitySerializer result.eInvoiceType = serializers.deserialize(value, specifiedType: const FullType(String)) as String; break; + case 'default_expense_payment_type_id': + result.defaultExpensePaymentTypeId = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; } } @@ -2914,6 +2925,8 @@ class _$SettingsEntity extends SettingsEntity { final bool showTaskItemDescription; @override final String eInvoiceType; + @override + final String defaultExpensePaymentTypeId; factory _$SettingsEntity([void Function(SettingsEntityBuilder) updates]) => (new SettingsEntityBuilder()..update(updates))._build(); @@ -3134,7 +3147,8 @@ class _$SettingsEntity extends SettingsEntity { this.shareInvoiceQuoteColumns, this.allowBillableTaskItems, this.showTaskItemDescription, - this.eInvoiceType}) + this.eInvoiceType, + this.defaultExpensePaymentTypeId}) : super._(); @override @@ -3369,7 +3383,8 @@ class _$SettingsEntity extends SettingsEntity { shareInvoiceQuoteColumns == other.shareInvoiceQuoteColumns && allowBillableTaskItems == other.allowBillableTaskItems && showTaskItemDescription == other.showTaskItemDescription && - eInvoiceType == other.eInvoiceType; + eInvoiceType == other.eInvoiceType && + defaultExpensePaymentTypeId == other.defaultExpensePaymentTypeId; } int __hashCode; @@ -3593,6 +3608,7 @@ class _$SettingsEntity extends SettingsEntity { _$hash = $jc(_$hash, allowBillableTaskItems.hashCode); _$hash = $jc(_$hash, showTaskItemDescription.hashCode); _$hash = $jc(_$hash, eInvoiceType.hashCode); + _$hash = $jc(_$hash, defaultExpensePaymentTypeId.hashCode); _$hash = $jf(_$hash); return __hashCode ??= _$hash; } @@ -3820,7 +3836,8 @@ class _$SettingsEntity extends SettingsEntity { ..add('shareInvoiceQuoteColumns', shareInvoiceQuoteColumns) ..add('allowBillableTaskItems', allowBillableTaskItems) ..add('showTaskItemDescription', showTaskItemDescription) - ..add('eInvoiceType', eInvoiceType)) + ..add('eInvoiceType', eInvoiceType) + ..add('defaultExpensePaymentTypeId', defaultExpensePaymentTypeId)) .toString(); } } @@ -4889,6 +4906,11 @@ class SettingsEntityBuilder String get eInvoiceType => _$this._eInvoiceType; set eInvoiceType(String eInvoiceType) => _$this._eInvoiceType = eInvoiceType; + String _defaultExpensePaymentTypeId; + String get defaultExpensePaymentTypeId => _$this._defaultExpensePaymentTypeId; + set defaultExpensePaymentTypeId(String defaultExpensePaymentTypeId) => + _$this._defaultExpensePaymentTypeId = defaultExpensePaymentTypeId; + SettingsEntityBuilder(); SettingsEntityBuilder get _$this { @@ -5110,6 +5132,7 @@ class SettingsEntityBuilder _allowBillableTaskItems = $v.allowBillableTaskItems; _showTaskItemDescription = $v.showTaskItemDescription; _eInvoiceType = $v.eInvoiceType; + _defaultExpensePaymentTypeId = $v.defaultExpensePaymentTypeId; _$v = null; } return this; @@ -5350,7 +5373,8 @@ class SettingsEntityBuilder shareInvoiceQuoteColumns: shareInvoiceQuoteColumns, allowBillableTaskItems: allowBillableTaskItems, showTaskItemDescription: showTaskItemDescription, - eInvoiceType: eInvoiceType); + eInvoiceType: eInvoiceType, + defaultExpensePaymentTypeId: defaultExpensePaymentTypeId); } catch (_) { String _$failedField; try { diff --git a/lib/ui/settings/expense_settings.dart b/lib/ui/settings/expense_settings.dart index 74782b543..9e9b23ee4 100644 --- a/lib/ui/settings/expense_settings.dart +++ b/lib/ui/settings/expense_settings.dart @@ -1,9 +1,12 @@ // Flutter imports: import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/data/models/entities.dart'; +import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; // Project imports: import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.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_form.dart'; import 'package:invoiceninja_flutter/ui/app/forms/bool_dropdown_button.dart'; @@ -43,7 +46,9 @@ class _ExpenseSettingsState extends State { Widget build(BuildContext context) { final localization = AppLocalization.of(context); final viewModel = widget.viewModel; + final state = viewModel.state; final company = viewModel.company; + final settings = viewModel.settings; return EditScaffold( title: localization.expenseSettings, @@ -70,6 +75,20 @@ class _ExpenseSettingsState extends State { onChanged: (value) => viewModel.onCompanyChanged( company.rebuild((b) => b..markExpensesPaid = value)), ), + if (company.markExpensesPaid == true) + Padding( + padding: const EdgeInsets.only(bottom: 20, top: 8), + child: EntityDropdown( + entityType: EntityType.paymentType, + entityList: memoizedPaymentTypeList( + state.staticState.paymentTypeMap), + labelText: localization.paymentType, + entityId: settings.defaultExpensePaymentTypeId, + onSelected: (paymentType) => viewModel.onSettingsChanged( + settings.rebuild((b) => + b..defaultExpensePaymentTypeId = paymentType?.id)), + ), + ), SwitchListTile( activeColor: Theme.of(context).colorScheme.secondary, title: Text(localization.convertCurrency), diff --git a/lib/ui/settings/expense_settings_vm.dart b/lib/ui/settings/expense_settings_vm.dart index ff472fa95..6cbfe7dac 100644 --- a/lib/ui/settings/expense_settings_vm.dart +++ b/lib/ui/settings/expense_settings_vm.dart @@ -4,6 +4,12 @@ import 'package:flutter/widgets.dart'; // Package imports: import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/data/models/client_model.dart'; +import 'package:invoiceninja_flutter/data/models/entities.dart'; +import 'package:invoiceninja_flutter/data/models/group_model.dart'; +import 'package:invoiceninja_flutter/data/models/settings_model.dart'; +import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; +import 'package:invoiceninja_flutter/redux/group/group_actions.dart'; import 'package:redux/redux.dart'; // Project imports: @@ -41,6 +47,8 @@ class ExpenseSettingsVM { @required this.onCompanyChanged, @required this.onSavePressed, @required this.onConfigureCategoriesPressed, + @required this.onSettingsChanged, + @required this.settings, }); static ExpenseSettingsVM fromStore(Store store) { @@ -49,15 +57,34 @@ class ExpenseSettingsVM { return ExpenseSettingsVM( state: state, company: state.uiState.settingsUIState.company, + settings: state.uiState.settingsUIState.settings, onCompanyChanged: (company) => store.dispatch(UpdateCompany(company: company)), + onSettingsChanged: (settings) => + store.dispatch(UpdateSettings(settings: settings)), onSavePressed: (context) { Debouncer.runOnComplete(() { final settingsUIState = store.state.uiState.settingsUIState; - final completer = snackBarCompleter( - context, AppLocalization.of(context).savedSettings); - store.dispatch(SaveCompanyRequest( - completer: completer, company: settingsUIState.company)); + switch (settingsUIState.entityType) { + case EntityType.company: + final completer = snackBarCompleter( + context, AppLocalization.of(context).savedSettings); + store.dispatch(SaveCompanyRequest( + completer: completer, company: settingsUIState.company)); + break; + case EntityType.group: + final completer = snackBarCompleter( + context, AppLocalization.of(context).savedSettings); + store.dispatch(SaveGroupRequest( + completer: completer, group: settingsUIState.group)); + break; + case EntityType.client: + final completer = snackBarCompleter( + context, AppLocalization.of(context).savedSettings); + store.dispatch(SaveClientRequest( + completer: completer, client: settingsUIState.client)); + break; + } }); }, onConfigureCategoriesPressed: (context) { @@ -69,6 +96,8 @@ class ExpenseSettingsVM { final AppState state; final Function(BuildContext) onSavePressed; final CompanyEntity company; + final SettingsEntity settings; final Function(CompanyEntity) onCompanyChanged; + final Function(SettingsEntity) onSettingsChanged; final Function(BuildContext) onConfigureCategoriesPressed; }