diff --git a/lib/data/models/expense_model.dart b/lib/data/models/expense_model.dart index c38aa36cf..16dff2b39 100644 --- a/lib/data/models/expense_model.dart +++ b/lib/data/models/expense_model.dart @@ -315,13 +315,26 @@ abstract class ExpenseEntity extends Object actions.add(EntityAction.edit); } - if (!isInvoiced && userCompany.canCreate(EntityType.invoice)) { + if (!isInvoiced && + !isRecurring && + userCompany.canCreate(EntityType.invoice)) { actions.add(EntityAction.invoiceExpense); } } - if (userCompany.canCreate(EntityType.task) && !multiselect) { - actions.add(EntityAction.clone); + if (userCompany.canCreate(EntityType.expense) && + !multiselect && + !isRecurring) { + actions.add(EntityAction.cloneToExpense); + } + + if (userCompany.canCreate(EntityType.recurringExpense) && !multiselect) { + actions.add(EntityAction.cloneToRecurring); + } + if (userCompany.canCreate(EntityType.expense) && + !multiselect && + isRecurring) { + actions.add(EntityAction.cloneToExpense); } if (actions.isNotEmpty && actions.last != null) { diff --git a/lib/data/models/models.dart b/lib/data/models/models.dart index 8b9f01afb..1e87a2fbe 100644 --- a/lib/data/models/models.dart +++ b/lib/data/models/models.dart @@ -53,6 +53,7 @@ class EntityAction extends EnumClass { static const EntityAction cloneToCredit = _$cloneToCredit; static const EntityAction cloneToInvoice = _$cloneToInvoice; static const EntityAction cloneToQuote = _$cloneToQuote; + static const EntityAction cloneToExpense = _$cloneToExpense; static const EntityAction cloneToRecurring = _$cloneToRecurring; static const EntityAction convertToInvoice = _$convertToInvoice; static const EntityAction approve = _$approve; diff --git a/lib/data/models/models.g.dart b/lib/data/models/models.g.dart index 13be67340..439bf3f44 100644 --- a/lib/data/models/models.g.dart +++ b/lib/data/models/models.g.dart @@ -16,6 +16,7 @@ const EntityAction _$cloneToOther = const EntityAction._('cloneToOther'); const EntityAction _$cloneToCredit = const EntityAction._('cloneToCredit'); const EntityAction _$cloneToInvoice = const EntityAction._('cloneToInvoice'); const EntityAction _$cloneToQuote = const EntityAction._('cloneToQuote'); +const EntityAction _$cloneToExpense = const EntityAction._('cloneToExpense'); const EntityAction _$cloneToRecurring = const EntityAction._('cloneToRecurring'); const EntityAction _$convertToInvoice = @@ -84,6 +85,8 @@ EntityAction _$valueOf(String name) { return _$cloneToInvoice; case 'cloneToQuote': return _$cloneToQuote; + case 'cloneToExpense': + return _$cloneToExpense; case 'cloneToRecurring': return _$cloneToRecurring; case 'convertToInvoice': @@ -179,6 +182,7 @@ final BuiltSet _$values = _$cloneToCredit, _$cloneToInvoice, _$cloneToQuote, + _$cloneToExpense, _$cloneToRecurring, _$convertToInvoice, _$approve, diff --git a/lib/redux/expense/expense_actions.dart b/lib/redux/expense/expense_actions.dart index 90503c0b7..e8ea6f4c3 100644 --- a/lib/redux/expense/expense_actions.dart +++ b/lib/redux/expense/expense_actions.dart @@ -255,8 +255,19 @@ void handleExpenseAction( case EntityAction.edit: editEntity(context: context, entity: expense); break; - case EntityAction.clone: - createEntity(context: context, entity: expense.clone); + case EntityAction.cloneToExpense: + createEntity( + context: context, + entity: + expense.clone.rebuild((b) => b..entityType = EntityType.expense), + ); + break; + case EntityAction.cloneToRecurring: + createEntity( + context: context, + entity: expense.clone + .rebuild((b) => b..entityType = EntityType.recurringExpense), + ); break; case EntityAction.invoiceExpense: final items = expenses diff --git a/lib/redux/expense/expense_middleware.dart b/lib/redux/expense/expense_middleware.dart index c2f18e50e..1a18e4553 100644 --- a/lib/redux/expense/expense_middleware.dart +++ b/lib/redux/expense/expense_middleware.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; +import 'package:invoiceninja_flutter/redux/recurring_expense/recurring_expense_actions.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; @@ -231,7 +232,7 @@ Middleware _loadExpenses(ExpenseRepository repository) { if (action.completer != null) { action.completer.complete(null); } - store.dispatch(PersistData()); + store.dispatch(LoadRecurringExpenses()); }).catchError((Object error) { print(error); store.dispatch(LoadExpensesFailure(error)); diff --git a/lib/redux/recurring_expense/recurring_expense_actions.dart b/lib/redux/recurring_expense/recurring_expense_actions.dart index b4d10ed4d..344307bbd 100644 --- a/lib/redux/recurring_expense/recurring_expense_actions.dart +++ b/lib/redux/recurring_expense/recurring_expense_actions.dart @@ -299,6 +299,20 @@ void handleRecurringExpenseAction(BuildContext context, context, localization.deletedRecurringExpense), recurringExpenseIds)); break; + case EntityAction.cloneToExpense: + createEntity( + context: context, + entity: recurringExpense.clone + .rebuild((b) => b..entityType = EntityType.expense), + ); + break; + case EntityAction.cloneToRecurring: + createEntity( + context: context, + entity: recurringExpense.clone + .rebuild((b) => b..entityType = EntityType.recurringExpense), + ); + break; case EntityAction.toggleMultiselect: if (!store.state.recurringExpenseListState.isInMultiselect()) { store.dispatch(StartRecurringExpenseMultiselect()); diff --git a/lib/redux/recurring_expense/recurring_expense_middleware.dart b/lib/redux/recurring_expense/recurring_expense_middleware.dart index 9cb81cd7e..1a443a003 100644 --- a/lib/redux/recurring_expense/recurring_expense_middleware.dart +++ b/lib/redux/recurring_expense/recurring_expense_middleware.dart @@ -236,11 +236,7 @@ Middleware _loadRecurringExpenses( if (action.completer != null) { action.completer.complete(null); } - /* - if (state.productState.isStale) { - store.dispatch(LoadProducts()); - } - */ + store.dispatch(PersistData()); }).catchError((Object error) { print(error); store.dispatch(LoadRecurringExpensesFailure(error)); diff --git a/lib/ui/expense/view/expense_view_overview.dart b/lib/ui/expense/view/expense_view_overview.dart index 977583ecb..1e6807f7e 100644 --- a/lib/ui/expense/view/expense_view_overview.dart +++ b/lib/ui/expense/view/expense_view_overview.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:invoiceninja_flutter/colors.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index d374fbf53..7e62d035b 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -15,6 +15,7 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'clone_to_expense': 'Clone to Expense', 'recurring_expense': 'Recurring Expense', 'recurring_expenses': 'Recurring Expenses', 'new_recurring_expense': 'New Recurring Expense', @@ -62589,6 +62590,10 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['search_recurring_expenses'] ?? _localizedValues['en']['search_recurring_expenses']; + String get cloneToExpense => + _localizedValues[localeCode]['clone_to_expense'] ?? + _localizedValues['en']['clone_to_expense']; + // STARTER: lang field - do not remove comment String lookup(String key) { diff --git a/lib/utils/icons.dart b/lib/utils/icons.dart index cb8d76aeb..16d5058e3 100644 --- a/lib/utils/icons.dart +++ b/lib/utils/icons.dart @@ -16,6 +16,7 @@ IconData getEntityActionIcon(EntityAction entityAction) { case EntityAction.clone: case EntityAction.cloneToOther: case EntityAction.cloneToInvoice: + case EntityAction.cloneToExpense: case EntityAction.cloneToQuote: case EntityAction.cloneToCredit: case EntityAction.cloneToRecurring: