Expenses
This commit is contained in:
parent
b45ffe6bd3
commit
a3014a86b6
|
|
@ -18,6 +18,7 @@ const String kSharedPrefEmailPayment = 'email_payment';
|
|||
const String kSharedPrefAutoStartTasks = 'auto_start_tasks';
|
||||
const String kSharedPrefAppVersion = 'app_version';
|
||||
const String kSharedPrefRequireAuthentication = 'require_authentication';
|
||||
const String kSharedPrefAddDocumentsToInvoice = 'add_documents_to_invoice';
|
||||
|
||||
String getCompanyTokenKey([int companyIndex = 0]) =>
|
||||
'${kSharedPrefToken}_$companyIndex';
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ abstract class BaseEntity implements SelectableEntity {
|
|||
|
||||
bool get isNew => id == null || id < 0;
|
||||
|
||||
bool get isOld => !isNew;
|
||||
|
||||
bool get isActive => archivedAt == null || archivedAt == 0;
|
||||
|
||||
bool get isArchived => archivedAt != null && archivedAt > 0 && !isDeleted;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:built_value/serializer.dart';
|
|||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
|
||||
part 'expense_model.g.dart';
|
||||
|
|
@ -67,13 +68,13 @@ abstract class ExpenseEntity extends Object
|
|||
with BaseEntity, SelectableEntity, BelongsToClient
|
||||
implements Built<ExpenseEntity, ExpenseEntityBuilder> {
|
||||
factory ExpenseEntity(
|
||||
{CompanyEntity company, VendorEntity vendor, ClientEntity client}) {
|
||||
{CompanyEntity company, UIState uiState, VendorEntity vendor, ClientEntity client}) {
|
||||
return _$ExpenseEntity._(
|
||||
id: --ExpenseEntity.counter,
|
||||
privateNotes: '',
|
||||
publicNotes: '',
|
||||
shouldBeInvoiced: false,
|
||||
invoiceDocuments: false,
|
||||
invoiceDocuments: uiState?.addDocumentsToInvoice ?? false,
|
||||
transactionId: '',
|
||||
transactionReference: '',
|
||||
bankId: 0,
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@ class UserSettingsChanged implements PersistUI {
|
|||
{this.enableDarkMode,
|
||||
this.emailPayment,
|
||||
this.requireAuthentication,
|
||||
this.autoStartTasks});
|
||||
this.autoStartTasks,
|
||||
this.addDocumentsToInvoice});
|
||||
|
||||
final bool enableDarkMode;
|
||||
final bool emailPayment;
|
||||
final bool requireAuthentication;
|
||||
final bool autoStartTasks;
|
||||
final bool addDocumentsToInvoice;
|
||||
}
|
||||
|
||||
class LoadDataSuccess {
|
||||
|
|
|
|||
|
|
@ -43,17 +43,15 @@ void _loadAuthLocal(Store<AppState> store, dynamic action) async {
|
|||
final String secret = prefs.getString(kSharedPrefSecret) ?? '';
|
||||
store.dispatch(UserLoginLoaded(email, url, secret));
|
||||
|
||||
final bool enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
|
||||
final bool emailPayment = prefs.getBool(kSharedPrefEmailPayment) ?? false;
|
||||
final bool autoStartTasks = prefs.getBool(kSharedPrefAutoStartTasks) ?? false;
|
||||
final bool requireAuthentication =
|
||||
prefs.getBool(kSharedPrefRequireAuthentication) ?? false;
|
||||
|
||||
store.dispatch(UserSettingsChanged(
|
||||
enableDarkMode: enableDarkMode,
|
||||
emailPayment: emailPayment,
|
||||
requireAuthentication: requireAuthentication,
|
||||
autoStartTasks: autoStartTasks));
|
||||
enableDarkMode: prefs.getBool(kSharedPrefEnableDarkMode) ?? false,
|
||||
emailPayment: prefs.getBool(kSharedPrefEmailPayment) ?? false,
|
||||
requireAuthentication:
|
||||
prefs.getBool(kSharedPrefRequireAuthentication) ?? false,
|
||||
autoStartTasks: prefs.getBool(kSharedPrefAutoStartTasks) ?? false,
|
||||
addDocumentsToInvoice:
|
||||
prefs.getBool(kSharedPrefAddDocumentsToInvoice) ?? false,
|
||||
));
|
||||
}
|
||||
|
||||
Middleware<AppState> _createLoginInit() {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ UIState uiReducer(UIState state, dynamic action) {
|
|||
..requireAuthentication =
|
||||
requireAuthenticationReducer(state.requireAuthentication, action)
|
||||
..emailPayment = emailPaymentReducer(state.emailPayment, action)
|
||||
..addDocumentsToInvoice =
|
||||
addDocumentsToInvoiceReducer(state.addDocumentsToInvoice, action)
|
||||
..productUIState.replace(productUIReducer(state.productUIState, action))
|
||||
..clientUIState.replace(clientUIReducer(state.clientUIState, action))
|
||||
..invoiceUIState.replace(invoiceUIReducer(state.invoiceUIState, action))
|
||||
|
|
@ -79,6 +81,15 @@ bool updateAutoStartTasksReducer(
|
|||
return action.autoStartTasks ?? autoStartTasks;
|
||||
}
|
||||
|
||||
Reducer<bool> addDocumentsToInvoiceReducer = combineReducers([
|
||||
TypedReducer<bool, UserSettingsChanged>(updateAddDocumentsToInvoiceReducer),
|
||||
]);
|
||||
|
||||
bool updateAddDocumentsToInvoiceReducer(
|
||||
bool addDocumentsToInvoice, UserSettingsChanged action) {
|
||||
return action.addDocumentsToInvoice ?? addDocumentsToInvoice;
|
||||
}
|
||||
|
||||
Reducer<bool> requireAuthenticationReducer = combineReducers([
|
||||
TypedReducer<bool, UserSettingsChanged>(updateRequireAuthenticationReducer),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
requireAuthentication: requireAuthentication ?? false,
|
||||
emailPayment: false,
|
||||
autoStartTasks: false,
|
||||
addDocumentsToInvoice: false,
|
||||
dashboardUIState: DashboardUIState(),
|
||||
productUIState: ProductUIState(),
|
||||
clientUIState: ClientUIState(),
|
||||
|
|
@ -60,6 +61,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
|
||||
bool get autoStartTasks;
|
||||
|
||||
bool get addDocumentsToInvoice;
|
||||
|
||||
@nullable
|
||||
String get filter;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
|||
'autoStartTasks',
|
||||
serializers.serialize(object.autoStartTasks,
|
||||
specifiedType: const FullType(bool)),
|
||||
'addDocumentsToInvoice',
|
||||
serializers.serialize(object.addDocumentsToInvoice,
|
||||
specifiedType: const FullType(bool)),
|
||||
'dashboardUIState',
|
||||
serializers.serialize(object.dashboardUIState,
|
||||
specifiedType: const FullType(DashboardUIState)),
|
||||
|
|
@ -125,6 +128,10 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
|||
result.autoStartTasks = serializers.deserialize(value,
|
||||
specifiedType: const FullType(bool)) as bool;
|
||||
break;
|
||||
case 'addDocumentsToInvoice':
|
||||
result.addDocumentsToInvoice = serializers.deserialize(value,
|
||||
specifiedType: const FullType(bool)) as bool;
|
||||
break;
|
||||
case 'filter':
|
||||
result.filter = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
|
|
@ -191,6 +198,8 @@ class _$UIState extends UIState {
|
|||
@override
|
||||
final bool autoStartTasks;
|
||||
@override
|
||||
final bool addDocumentsToInvoice;
|
||||
@override
|
||||
final String filter;
|
||||
@override
|
||||
final DashboardUIState dashboardUIState;
|
||||
|
|
@ -223,6 +232,7 @@ class _$UIState extends UIState {
|
|||
this.requireAuthentication,
|
||||
this.emailPayment,
|
||||
this.autoStartTasks,
|
||||
this.addDocumentsToInvoice,
|
||||
this.filter,
|
||||
this.dashboardUIState,
|
||||
this.productUIState,
|
||||
|
|
@ -253,6 +263,9 @@ class _$UIState extends UIState {
|
|||
if (autoStartTasks == null) {
|
||||
throw new BuiltValueNullFieldError('UIState', 'autoStartTasks');
|
||||
}
|
||||
if (addDocumentsToInvoice == null) {
|
||||
throw new BuiltValueNullFieldError('UIState', 'addDocumentsToInvoice');
|
||||
}
|
||||
if (dashboardUIState == null) {
|
||||
throw new BuiltValueNullFieldError('UIState', 'dashboardUIState');
|
||||
}
|
||||
|
|
@ -302,6 +315,7 @@ class _$UIState extends UIState {
|
|||
requireAuthentication == other.requireAuthentication &&
|
||||
emailPayment == other.emailPayment &&
|
||||
autoStartTasks == other.autoStartTasks &&
|
||||
addDocumentsToInvoice == other.addDocumentsToInvoice &&
|
||||
filter == other.filter &&
|
||||
dashboardUIState == other.dashboardUIState &&
|
||||
productUIState == other.productUIState &&
|
||||
|
|
@ -334,17 +348,22 @@ class _$UIState extends UIState {
|
|||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
0,
|
||||
selectedCompanyIndex
|
||||
$jc(
|
||||
0,
|
||||
selectedCompanyIndex
|
||||
.hashCode),
|
||||
currentRoute
|
||||
.hashCode),
|
||||
currentRoute
|
||||
enableDarkMode
|
||||
.hashCode),
|
||||
enableDarkMode
|
||||
requireAuthentication
|
||||
.hashCode),
|
||||
requireAuthentication
|
||||
emailPayment
|
||||
.hashCode),
|
||||
emailPayment.hashCode),
|
||||
autoStartTasks.hashCode),
|
||||
autoStartTasks
|
||||
.hashCode),
|
||||
addDocumentsToInvoice
|
||||
.hashCode),
|
||||
filter.hashCode),
|
||||
dashboardUIState.hashCode),
|
||||
productUIState.hashCode),
|
||||
|
|
@ -367,6 +386,7 @@ class _$UIState extends UIState {
|
|||
..add('requireAuthentication', requireAuthentication)
|
||||
..add('emailPayment', emailPayment)
|
||||
..add('autoStartTasks', autoStartTasks)
|
||||
..add('addDocumentsToInvoice', addDocumentsToInvoice)
|
||||
..add('filter', filter)
|
||||
..add('dashboardUIState', dashboardUIState)
|
||||
..add('productUIState', productUIState)
|
||||
|
|
@ -413,6 +433,11 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
|||
set autoStartTasks(bool autoStartTasks) =>
|
||||
_$this._autoStartTasks = autoStartTasks;
|
||||
|
||||
bool _addDocumentsToInvoice;
|
||||
bool get addDocumentsToInvoice => _$this._addDocumentsToInvoice;
|
||||
set addDocumentsToInvoice(bool addDocumentsToInvoice) =>
|
||||
_$this._addDocumentsToInvoice = addDocumentsToInvoice;
|
||||
|
||||
String _filter;
|
||||
String get filter => _$this._filter;
|
||||
set filter(String filter) => _$this._filter = filter;
|
||||
|
|
@ -487,6 +512,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
|||
_requireAuthentication = _$v.requireAuthentication;
|
||||
_emailPayment = _$v.emailPayment;
|
||||
_autoStartTasks = _$v.autoStartTasks;
|
||||
_addDocumentsToInvoice = _$v.addDocumentsToInvoice;
|
||||
_filter = _$v.filter;
|
||||
_dashboardUIState = _$v.dashboardUIState?.toBuilder();
|
||||
_productUIState = _$v.productUIState?.toBuilder();
|
||||
|
|
@ -528,6 +554,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
|||
requireAuthentication: requireAuthentication,
|
||||
emailPayment: emailPayment,
|
||||
autoStartTasks: autoStartTasks,
|
||||
addDocumentsToInvoice: addDocumentsToInvoice,
|
||||
filter: filter,
|
||||
dashboardUIState: dashboardUIState.build(),
|
||||
productUIState: productUIState.build(),
|
||||
|
|
|
|||
|
|
@ -264,7 +264,9 @@ class AppDrawer extends StatelessWidget {
|
|||
onCreateTap: () {
|
||||
navigator.pop();
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(company: company), context: context));
|
||||
expense:
|
||||
ExpenseEntity(company: company, uiState: state.uiState),
|
||||
context: context));
|
||||
},
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ class ClientListVM {
|
|||
break;
|
||||
case EntityAction.newExpense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(company: state.selectedCompany, client: client),
|
||||
expense: ExpenseEntity(
|
||||
company: state.selectedCompany,
|
||||
client: client,
|
||||
uiState: state.uiState),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.enterPayment:
|
||||
|
|
|
|||
|
|
@ -160,7 +160,9 @@ class _ClientViewState extends State<ClientView>
|
|||
Navigator.of(context).pop();
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(
|
||||
company: company, client: client),
|
||||
company: company,
|
||||
client: client,
|
||||
uiState: store.state.uiState),
|
||||
context: context));
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -155,7 +155,9 @@ class ClientViewVM {
|
|||
store.dispatch(EditExpense(
|
||||
context: context,
|
||||
expense: ExpenseEntity(
|
||||
company: state.selectedCompany, client: client)));
|
||||
company: state.selectedCompany,
|
||||
client: client,
|
||||
uiState: state.uiState)));
|
||||
} else {
|
||||
store.dispatch(FilterExpensesByEntity(
|
||||
entityId: client.id, entityType: EntityType.client));
|
||||
|
|
@ -183,7 +185,9 @@ class ClientViewVM {
|
|||
case EntityAction.newExpense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(
|
||||
company: state.selectedCompany, client: client),
|
||||
company: state.selectedCompany,
|
||||
client: client,
|
||||
uiState: state.uiState),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.enterPayment:
|
||||
|
|
|
|||
|
|
@ -67,8 +67,11 @@ class ExpenseEditDocumentsState extends State<ExpenseEditDocuments> {
|
|||
activeColor: Theme.of(context).accentColor,
|
||||
title: Text(localization.addDocumentsToInvoice),
|
||||
value: expense.invoiceDocuments,
|
||||
onChanged: (value) => viewModel.onChanged(
|
||||
expense.rebuild((b) => b..invoiceDocuments = value)),
|
||||
onChanged: (value) {
|
||||
viewModel.onChanged(
|
||||
expense.rebuild((b) => b..invoiceDocuments = value));
|
||||
viewModel.onAddDocumentsChanged(value);
|
||||
}
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -138,8 +138,10 @@ class ExpenseEditSettingsState extends State<ExpenseEditSettings> {
|
|||
activeColor: Theme.of(context).accentColor,
|
||||
title: Text(localization.markBillable),
|
||||
value: expense.shouldBeInvoiced,
|
||||
onChanged: (value) => viewModel.onChanged(
|
||||
expense.rebuild((b) => b..shouldBeInvoiced = value)),
|
||||
onChanged: (value) {
|
||||
viewModel.onChanged(
|
||||
expense.rebuild((b) => b..shouldBeInvoiced = value));
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
activeColor: Theme.of(context).accentColor,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import 'dart:async';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||
|
|
@ -16,6 +18,7 @@ import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
|||
import 'package:invoiceninja_flutter/data/models/expense_model.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class ExpenseEditScreen extends StatelessWidget {
|
||||
const ExpenseEditScreen({Key key}) : super(key: key);
|
||||
|
|
@ -49,6 +52,7 @@ class ExpenseEditVM {
|
|||
@required this.isLoading,
|
||||
@required this.onAddClientPressed,
|
||||
@required this.onAddVendorPressed,
|
||||
@required this.onAddDocumentsChanged,
|
||||
});
|
||||
|
||||
factory ExpenseEditVM.fromStore(Store<AppState> store) {
|
||||
|
|
@ -120,6 +124,14 @@ class ExpenseEditVM {
|
|||
});
|
||||
});
|
||||
},
|
||||
onAddDocumentsChanged: (value) async {
|
||||
if (expense.isOld) {
|
||||
return;
|
||||
}
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setBool(kSharedPrefEmailPayment, value);
|
||||
store.dispatch(UserSettingsChanged(addDocumentsToInvoice: value));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -136,4 +148,5 @@ class ExpenseEditVM {
|
|||
onAddClientPressed;
|
||||
final Function(BuildContext context, Completer<SelectableEntity> completer)
|
||||
onAddVendorPressed;
|
||||
final Function(bool) onAddDocumentsChanged;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,8 @@ class ExpenseScreen extends StatelessWidget {
|
|||
backgroundColor: Theme.of(context).primaryColorDark,
|
||||
onPressed: () {
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(company: company),
|
||||
expense: ExpenseEntity(
|
||||
company: company, uiState: store.state.uiState),
|
||||
context: context));
|
||||
},
|
||||
child: Icon(
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ class PaymentEditVM {
|
|||
store.dispatch(UpdatePayment(payment));
|
||||
},
|
||||
onEmailChanged: (value) async {
|
||||
if (payment.isOld) {
|
||||
return;
|
||||
}
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setBool(kSharedPrefEmailPayment, value);
|
||||
store.dispatch(UserSettingsChanged(emailPayment: value));
|
||||
|
|
|
|||
Loading…
Reference in New Issue