From 3a484b26b6350320692efcac84ffa42edd696bcc Mon Sep 17 00:00:00 2001 From: Gianfranco Gasbarri Date: Sun, 27 Oct 2019 13:24:30 +0000 Subject: [PATCH] Implement Bulk for Invoices --- lib/data/repositories/invoice_repository.dart | 26 +++++ lib/redux/invoice/invoice_actions.dart | 43 +++---- lib/redux/invoice/invoice_middleware.dart | 43 ++++--- lib/redux/invoice/invoice_reducer.dart | 108 +++++++++++------- 4 files changed, 142 insertions(+), 78 deletions(-) diff --git a/lib/data/repositories/invoice_repository.dart b/lib/data/repositories/invoice_repository.dart index 04b6acf7d..ffd68b46e 100644 --- a/lib/data/repositories/invoice_repository.dart +++ b/lib/data/repositories/invoice_repository.dart @@ -44,6 +44,32 @@ class InvoiceRepository { return invoiceResponse.data; } + Future> bulkAction( + Credentials credentials, List ids, EntityAction action) async { + dynamic response; + + switch (action) { + case EntityAction.restore: + case EntityAction.archive: + case EntityAction.delete: + var url = credentials.url + '/invoices/bulk?include=activities'; + if (action != null) { + url += '&action=' + action.toString(); + } + response = await webClient.put(url, credentials.token, + data: json.encode([ids])); + break; + default: + // Might have other actions in the future + break; + } + + final InvoiceListResponse invoiceResponse = + serializers.deserializeWith(InvoiceListResponse.serializer, response); + + return invoiceResponse.data.toList(); + } + Future saveData(Credentials credentials, InvoiceEntity invoice, [EntityAction action]) async { final data = serializers.serializeWith(InvoiceEntity.serializer, invoice); diff --git a/lib/redux/invoice/invoice_actions.dart b/lib/redux/invoice/invoice_actions.dart index 0f3f9802f..f88e466b5 100644 --- a/lib/redux/invoice/invoice_actions.dart +++ b/lib/redux/invoice/invoice_actions.dart @@ -214,60 +214,60 @@ class MarkSentInvoiceFailure implements StopSaving { } class ArchiveInvoiceRequest implements StartSaving { - ArchiveInvoiceRequest(this.completer, this.invoiceId); + ArchiveInvoiceRequest(this.completer, this.invoiceIds); final Completer completer; - final String invoiceId; + final List invoiceIds; } class ArchiveInvoiceSuccess implements StopSaving, PersistData { - ArchiveInvoiceSuccess(this.invoice); + ArchiveInvoiceSuccess(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class ArchiveInvoiceFailure implements StopSaving { - ArchiveInvoiceFailure(this.invoice); + ArchiveInvoiceFailure(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class DeleteInvoiceRequest implements StartSaving { - DeleteInvoiceRequest(this.completer, this.invoiceId); + DeleteInvoiceRequest(this.completer, this.invoiceIds); final Completer completer; - final String invoiceId; + final List invoiceIds; } class DeleteInvoiceSuccess implements StopSaving, PersistData { - DeleteInvoiceSuccess(this.invoice); + DeleteInvoiceSuccess(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class DeleteInvoiceFailure implements StopSaving { - DeleteInvoiceFailure(this.invoice); + DeleteInvoiceFailure(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class RestoreInvoiceRequest implements StartSaving { - RestoreInvoiceRequest(this.completer, this.invoiceId); + RestoreInvoiceRequest(this.completer, this.invoiceIds); final Completer completer; - final String invoiceId; + final List invoiceIds; } class RestoreInvoiceSuccess implements StopSaving, PersistData { - RestoreInvoiceSuccess(this.invoice); + RestoreInvoiceSuccess(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class RestoreInvoiceFailure implements StopSaving { - RestoreInvoiceFailure(this.invoice); + RestoreInvoiceFailure(this.invoices); - final InvoiceEntity invoice; + final List invoices; } class FilterInvoices { @@ -336,6 +336,7 @@ void handleInvoiceAction(BuildContext context, List invoices, final CompanyEntity company = state.selectedCompany; final localization = AppLocalization.of(context); final invoice = invoices.first as InvoiceEntity; + final invoiceIds = invoices.map((invoice) => invoice.id).toList(); switch (action) { case EntityAction.edit: @@ -375,16 +376,16 @@ void handleInvoiceAction(BuildContext context, List invoices, case EntityAction.restore: store.dispatch(RestoreInvoiceRequest( snackBarCompleter(context, localization.restoredInvoice), - invoice.id)); + invoiceIds)); break; case EntityAction.archive: store.dispatch(ArchiveInvoiceRequest( snackBarCompleter(context, localization.archivedInvoice), - invoice.id)); + invoiceIds)); break; case EntityAction.delete: store.dispatch(DeleteInvoiceRequest( - snackBarCompleter(context, localization.deletedInvoice), invoice.id)); + snackBarCompleter(context, localization.deletedInvoice), invoiceIds)); break; case EntityAction.toggleMultiselect: if (!store.state.invoiceListState.isInMultiselect()) { diff --git a/lib/redux/invoice/invoice_middleware.dart b/lib/redux/invoice/invoice_middleware.dart index d5d3d01a7..cb1ed7608 100644 --- a/lib/redux/invoice/invoice_middleware.dart +++ b/lib/redux/invoice/invoice_middleware.dart @@ -137,17 +137,20 @@ Middleware _showEmailInvoice() { Middleware _archiveInvoice(InvoiceRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as ArchiveInvoiceRequest; - final origInvoice = store.state.invoiceState.map[action.invoiceId]; repository - .saveData(store.state.credentials, origInvoice, EntityAction.archive) - .then((InvoiceEntity invoice) { - store.dispatch(ArchiveInvoiceSuccess(invoice)); + .bulkAction( + store.state.credentials, action.invoiceIds, EntityAction.archive) + .then((List invoices) { + store.dispatch(ArchiveInvoiceSuccess(invoices)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); - store.dispatch(ArchiveInvoiceFailure(origInvoice)); + final invoices = action.invoiceIds + .map((id) => store.state.invoiceState.map[id]) + .toList(); + store.dispatch(ArchiveInvoiceFailure(invoices)); if (action.completer != null) { action.completer.completeError(error); } @@ -160,18 +163,21 @@ Middleware _archiveInvoice(InvoiceRepository repository) { Middleware _deleteInvoice(InvoiceRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as DeleteInvoiceRequest; - final origInvoice = store.state.invoiceState.map[action.invoiceId]; repository - .saveData(store.state.credentials, origInvoice, EntityAction.delete) - .then((InvoiceEntity invoice) { - store.dispatch(DeleteInvoiceSuccess(invoice)); - store.dispatch(LoadClient(clientId: invoice.clientId)); + .bulkAction( + store.state.credentials, action.invoiceIds, EntityAction.delete) + .then((List invoices) { + store.dispatch(DeleteInvoiceSuccess(invoices)); + store.dispatch(LoadClient(clientId: invoices.first.clientId)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); - store.dispatch(DeleteInvoiceFailure(origInvoice)); + final invoices = action.invoiceIds + .map((id) => store.state.invoiceState.map[id]) + .toList(); + store.dispatch(DeleteInvoiceFailure(invoices)); if (action.completer != null) { action.completer.completeError(error); } @@ -184,18 +190,21 @@ Middleware _deleteInvoice(InvoiceRepository repository) { Middleware _restoreInvoice(InvoiceRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as RestoreInvoiceRequest; - final origInvoice = store.state.invoiceState.map[action.invoiceId]; repository - .saveData(store.state.credentials, origInvoice, EntityAction.restore) - .then((InvoiceEntity invoice) { - store.dispatch(RestoreInvoiceSuccess(invoice)); - store.dispatch(LoadClient(clientId: invoice.clientId)); + .bulkAction( + store.state.credentials, action.invoiceIds, EntityAction.restore) + .then((List invoices) { + store.dispatch(RestoreInvoiceSuccess(invoices)); + store.dispatch(LoadClient(clientId: invoices.first.clientId)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); - store.dispatch(RestoreInvoiceFailure(origInvoice)); + final invoices = action.invoiceIds + .map((id) => store.state.invoiceState.map[id]) + .toList(); + store.dispatch(RestoreInvoiceFailure(invoices)); if (action.completer != null) { action.completer.completeError(error); } diff --git a/lib/redux/invoice/invoice_reducer.dart b/lib/redux/invoice/invoice_reducer.dart index c66cc5cab..bff28051c 100644 --- a/lib/redux/invoice/invoice_reducer.dart +++ b/lib/redux/invoice/invoice_reducer.dart @@ -28,10 +28,10 @@ InvoiceItemEntity editInvoiceItem( } Reducer dropdownFilterReducer = combineReducers([ - TypedReducer(filterClientDropdownReducer), + TypedReducer(filterInvoiceDropdownReducer), ]); -String filterClientDropdownReducer( +String filterInvoiceDropdownReducer( String dropdownFilter, FilterInvoiceDropdown action) { return action.filter; } @@ -64,7 +64,7 @@ final editingReducer = combineReducers([ TypedReducer(_clearEditing), ]); -InvoiceEntity _clearEditing(InvoiceEntity client, dynamic action) { +InvoiceEntity _clearEditing(InvoiceEntity invoice, dynamic action) { return InvoiceEntity(); } @@ -189,8 +189,7 @@ ListUIState _startListMultiselect( ListUIState _addToListMultiselect( ListUIState invoiceListState, AddToInvoiceMultiselect action) { - return invoiceListState - .rebuild((b) => b..selectedIds.add(action.entity.id)); + return invoiceListState.rebuild((b) => b..selectedIds.add(action.entity.id)); } ListUIState _removeFromListMultiselect( @@ -230,75 +229,104 @@ InvoiceState _markSentInvoiceSuccess( InvoiceState _archiveInvoiceRequest( InvoiceState invoiceState, ArchiveInvoiceRequest action) { - final invoice = invoiceState.map[action.invoiceId] - .rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch); + final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList(); - return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice); + for (int i = 0; i < invoices.length; i++) { + invoices[i] = invoices[i] + .rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch); + } + + return invoiceState.rebuild((b) { + for (final invoice in invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _archiveInvoiceSuccess( InvoiceState invoiceState, ArchiveInvoiceSuccess action) { - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _archiveInvoiceFailure( InvoiceState invoiceState, ArchiveInvoiceFailure action) { - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _deleteInvoiceRequest( InvoiceState invoiceState, DeleteInvoiceRequest action) { - if (!invoiceState.map.containsKey(action.invoiceId)) { - return invoiceState; + final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList(); + + for (int i = 0; i < invoices.length; i++) { + invoices[i] = invoices[i].rebuild((b) => b + ..archivedAt = DateTime.now().millisecondsSinceEpoch + ..isDeleted = true); } - - final invoice = invoiceState.map[action.invoiceId].rebuild((b) => b - ..archivedAt = DateTime.now().millisecondsSinceEpoch - ..isDeleted = true); - - return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice); + return invoiceState.rebuild((b) { + for (final invoice in invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _deleteInvoiceSuccess( InvoiceState invoiceState, DeleteInvoiceSuccess action) { - if (!invoiceState.map.containsKey(action.invoice.id)) { - return invoiceState; - } - - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _deleteInvoiceFailure( InvoiceState invoiceState, DeleteInvoiceFailure action) { - if (!invoiceState.map.containsKey(action.invoice.id)) { - return invoiceState; - } - - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _restoreInvoiceRequest( InvoiceState invoiceState, RestoreInvoiceRequest action) { - final invoice = invoiceState.map[action.invoiceId].rebuild((b) => b - ..archivedAt = null - ..isDeleted = false); - return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice); + final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList(); + + for (int i = 0; i < invoices.length; i++) { + invoices[i] = invoices[i].rebuild((b) => b + ..archivedAt = null + ..isDeleted = false); + } + return invoiceState.rebuild((b) { + for (final invoice in invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _restoreInvoiceSuccess( InvoiceState invoiceState, RestoreInvoiceSuccess action) { - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _restoreInvoiceFailure( InvoiceState invoiceState, RestoreInvoiceFailure action) { - return invoiceState - .rebuild((b) => b..map[action.invoice.id] = action.invoice); + return invoiceState.rebuild((b) { + for (final invoice in action.invoices) { + b.map[invoice.id] = invoice; + } + }); } InvoiceState _addInvoice(InvoiceState invoiceState, AddInvoiceSuccess action) {