Purchase orders
This commit is contained in:
parent
c41a7ed225
commit
958e5fa0c7
|
|
@ -597,7 +597,7 @@ const Map<int, String> kModules = {
|
|||
kModuleProjects: 'projects',
|
||||
kModuleTasks: 'tasks',
|
||||
kModuleVendors: 'vendors',
|
||||
//kModulePurchaseOrders: 'purchase_orders',
|
||||
kModulePurchaseOrders: 'purchase_orders',
|
||||
kModuleExpenses: 'expenses',
|
||||
kModuleRecurringExpenses: 'recurring_expenses',
|
||||
//kModuleTickets: 'tickets',
|
||||
|
|
|
|||
|
|
@ -699,15 +699,12 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
|||
case PurchaseOrderEditScreen.route:
|
||||
return hasPurchaseOrderChanges(
|
||||
purchaseOrderUIState.editing, purchaseOrderState.map);
|
||||
|
||||
case RecurringExpenseEditScreen.route:
|
||||
return hasRecurringExpenseChanges(
|
||||
recurringExpenseUIState.editing, recurringExpenseState.map);
|
||||
|
||||
case SubscriptionEditScreen.route:
|
||||
return hasSubscriptionChanges(
|
||||
subscriptionUIState.editing, subscriptionState.map);
|
||||
|
||||
case TaskStatusEditScreen.route:
|
||||
return hasTaskStatusChanges(
|
||||
taskStatusUIState.editing, taskStatusState.map);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,28 @@ class EditPurchaseOrder implements PersistUI, PersistPrefs {
|
|||
final bool force;
|
||||
}
|
||||
|
||||
class ShowEmailPurchaseOrder {
|
||||
ShowEmailPurchaseOrder({this.purchaseOrder, this.context, this.completer});
|
||||
|
||||
final InvoiceEntity purchaseOrder;
|
||||
final BuildContext context;
|
||||
final Completer completer;
|
||||
}
|
||||
|
||||
class ShowPdfPurchaseOrder {
|
||||
ShowPdfPurchaseOrder({this.purchaseOrder, this.context, this.activityId});
|
||||
|
||||
final InvoiceEntity purchaseOrder;
|
||||
final BuildContext context;
|
||||
final String activityId;
|
||||
}
|
||||
|
||||
class EditPurchaseOrderItem implements PersistUI {
|
||||
EditPurchaseOrderItem([this.itemIndex]);
|
||||
|
||||
final int itemIndex;
|
||||
}
|
||||
|
||||
class UpdatePurchaseOrder implements PersistUI {
|
||||
UpdatePurchaseOrder(this.purchaseOrder);
|
||||
|
||||
|
|
@ -113,10 +135,15 @@ class LoadPurchaseOrdersSuccess implements StopLoading {
|
|||
}
|
||||
|
||||
class SavePurchaseOrderRequest implements StartSaving {
|
||||
SavePurchaseOrderRequest({this.completer, this.purchaseOrder});
|
||||
SavePurchaseOrderRequest({
|
||||
this.completer,
|
||||
this.purchaseOrder,
|
||||
this.action,
|
||||
});
|
||||
|
||||
final Completer completer;
|
||||
final InvoiceEntity purchaseOrder;
|
||||
final EntityAction action;
|
||||
}
|
||||
|
||||
class SavePurchaseOrderSuccess implements StopSaving, PersistData, PersistUI {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ abstract class PurchaseOrderUIState extends Object
|
|||
@nullable
|
||||
InvoiceEntity get editing;
|
||||
|
||||
@nullable
|
||||
@BuiltValueField(serialize: false)
|
||||
int get editingItemIndex;
|
||||
|
||||
@override
|
||||
bool get isCreatingNew => editing.isNew;
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,8 @@ class _$PurchaseOrderUIState extends PurchaseOrderUIState {
|
|||
@override
|
||||
final InvoiceEntity editing;
|
||||
@override
|
||||
final int editingItemIndex;
|
||||
@override
|
||||
final ListUIState listUIState;
|
||||
@override
|
||||
final String selectedId;
|
||||
|
|
@ -282,6 +284,7 @@ class _$PurchaseOrderUIState extends PurchaseOrderUIState {
|
|||
|
||||
_$PurchaseOrderUIState._(
|
||||
{this.editing,
|
||||
this.editingItemIndex,
|
||||
this.listUIState,
|
||||
this.selectedId,
|
||||
this.forceSelected,
|
||||
|
|
@ -309,6 +312,7 @@ class _$PurchaseOrderUIState extends PurchaseOrderUIState {
|
|||
if (identical(other, this)) return true;
|
||||
return other is PurchaseOrderUIState &&
|
||||
editing == other.editing &&
|
||||
editingItemIndex == other.editingItemIndex &&
|
||||
listUIState == other.listUIState &&
|
||||
selectedId == other.selectedId &&
|
||||
forceSelected == other.forceSelected &&
|
||||
|
|
@ -324,7 +328,11 @@ class _$PurchaseOrderUIState extends PurchaseOrderUIState {
|
|||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc($jc($jc(0, editing.hashCode), listUIState.hashCode),
|
||||
$jc(
|
||||
$jc(
|
||||
$jc($jc(0, editing.hashCode),
|
||||
editingItemIndex.hashCode),
|
||||
listUIState.hashCode),
|
||||
selectedId.hashCode),
|
||||
forceSelected.hashCode),
|
||||
tabIndex.hashCode),
|
||||
|
|
@ -336,6 +344,7 @@ class _$PurchaseOrderUIState extends PurchaseOrderUIState {
|
|||
String toString() {
|
||||
return (newBuiltValueToStringHelper('PurchaseOrderUIState')
|
||||
..add('editing', editing)
|
||||
..add('editingItemIndex', editingItemIndex)
|
||||
..add('listUIState', listUIState)
|
||||
..add('selectedId', selectedId)
|
||||
..add('forceSelected', forceSelected)
|
||||
|
|
@ -355,6 +364,11 @@ class PurchaseOrderUIStateBuilder
|
|||
_$this._editing ??= new InvoiceEntityBuilder();
|
||||
set editing(InvoiceEntityBuilder editing) => _$this._editing = editing;
|
||||
|
||||
int _editingItemIndex;
|
||||
int get editingItemIndex => _$this._editingItemIndex;
|
||||
set editingItemIndex(int editingItemIndex) =>
|
||||
_$this._editingItemIndex = editingItemIndex;
|
||||
|
||||
ListUIStateBuilder _listUIState;
|
||||
ListUIStateBuilder get listUIState =>
|
||||
_$this._listUIState ??= new ListUIStateBuilder();
|
||||
|
|
@ -390,6 +404,7 @@ class PurchaseOrderUIStateBuilder
|
|||
final $v = _$v;
|
||||
if ($v != null) {
|
||||
_editing = $v.editing?.toBuilder();
|
||||
_editingItemIndex = $v.editingItemIndex;
|
||||
_listUIState = $v.listUIState.toBuilder();
|
||||
_selectedId = $v.selectedId;
|
||||
_forceSelected = $v.forceSelected;
|
||||
|
|
@ -419,6 +434,7 @@ class PurchaseOrderUIStateBuilder
|
|||
_$result = _$v ??
|
||||
new _$PurchaseOrderUIState._(
|
||||
editing: _editing?.build(),
|
||||
editingItemIndex: editingItemIndex,
|
||||
listUIState: listUIState.build(),
|
||||
selectedId: selectedId,
|
||||
forceSelected: forceSelected,
|
||||
|
|
@ -431,6 +447,7 @@ class PurchaseOrderUIStateBuilder
|
|||
try {
|
||||
_$failedField = 'editing';
|
||||
_editing?.build();
|
||||
|
||||
_$failedField = 'listUIState';
|
||||
listUIState.build();
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ InvoiceEntity _clearEditing(InvoiceEntity quote, dynamic action) {
|
|||
}
|
||||
|
||||
InvoiceEntity _updateEditing(InvoiceEntity quote, dynamic action) {
|
||||
return action.quote;
|
||||
return action.purchaseOrder;
|
||||
}
|
||||
|
||||
InvoiceEntity _addQuoteItem(InvoiceEntity quote, AddQuoteItem action) {
|
||||
|
|
@ -367,7 +367,7 @@ QuoteState _addQuote(QuoteState quoteState, AddQuoteSuccess action) {
|
|||
}
|
||||
|
||||
QuoteState _updateQuote(QuoteState invoiceState, dynamic action) {
|
||||
final InvoiceEntity quote = action.quote;
|
||||
final InvoiceEntity quote = action.purchaseOrder;
|
||||
return invoiceState.rebuild((b) => b
|
||||
..map[quote.id] = quote
|
||||
.rebuild((b) => b..loadedAt = DateTime.now().millisecondsSinceEpoch));
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class _PurchaseOrderEditState extends State<PurchaseOrderEdit> {
|
|||
Widget build(BuildContext context) {
|
||||
final viewModel = widget.viewModel;
|
||||
final localization = AppLocalization.of(context);
|
||||
final purchaseOrder = viewModel.purchaseOrder;
|
||||
final purchaseOrder = viewModel.invoice;
|
||||
|
||||
return EditScaffold(
|
||||
title: purchaseOrder.isNew
|
||||
|
|
|
|||
|
|
@ -1,21 +1,31 @@
|
|||
// Dart imports:
|
||||
import 'dart:async';
|
||||
|
||||
// Flutter imports:
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Package imports:
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/purchase_order/view/purchase_order_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/redux/purchase_order/purchase_order_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/purchase_order/edit/purchase_order_edit.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/redux/purchase_order/purchase_order_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/purchase_order/purchase_order_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/purchase_order/edit/purchase_order_edit.dart';
|
||||
import 'package:invoiceninja_flutter/ui/purchase_order/view/purchase_order_view_vm.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
|
||||
// Project imports:
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/main_app.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
|
||||
class PurchaseOrderEditScreen extends StatelessWidget {
|
||||
const PurchaseOrderEditScreen({Key key}) : super(key: key);
|
||||
|
||||
static const String route = '/purchase_order/edit';
|
||||
|
||||
@override
|
||||
|
|
@ -27,90 +37,130 @@ class PurchaseOrderEditScreen extends StatelessWidget {
|
|||
builder: (context, viewModel) {
|
||||
return PurchaseOrderEdit(
|
||||
viewModel: viewModel,
|
||||
key: ValueKey(viewModel.purchaseOrder.updatedAt),
|
||||
key: ValueKey(viewModel.invoice.updatedAt),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PurchaseOrderEditVM {
|
||||
class PurchaseOrderEditVM extends AbstractInvoiceEditVM {
|
||||
PurchaseOrderEditVM({
|
||||
@required this.state,
|
||||
@required this.purchaseOrder,
|
||||
@required this.company,
|
||||
@required this.onChanged,
|
||||
@required this.isSaving,
|
||||
@required this.origPurchaseOrder,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.isLoading,
|
||||
});
|
||||
AppState state,
|
||||
CompanyEntity company,
|
||||
InvoiceEntity purchaseOrder,
|
||||
int invoiceItemIndex,
|
||||
InvoiceEntity origInvoice,
|
||||
Function(BuildContext) onSavePressed,
|
||||
Function(List<InvoiceItemEntity>, String, String) onItemsAdded,
|
||||
bool isSaving,
|
||||
Function(BuildContext) onCancelPressed,
|
||||
}) : super(
|
||||
state: state,
|
||||
company: company,
|
||||
invoice: purchaseOrder,
|
||||
invoiceItemIndex: invoiceItemIndex,
|
||||
origInvoice: origInvoice,
|
||||
onSavePressed: onSavePressed,
|
||||
onItemsAdded: onItemsAdded,
|
||||
isSaving: isSaving,
|
||||
onCancelPressed: onCancelPressed,
|
||||
);
|
||||
|
||||
factory PurchaseOrderEditVM.fromStore(Store<AppState> store) {
|
||||
final state = store.state;
|
||||
final AppState state = store.state;
|
||||
final purchaseOrder = state.purchaseOrderUIState.editing;
|
||||
|
||||
return PurchaseOrderEditVM(
|
||||
state: state,
|
||||
isLoading: state.isLoading,
|
||||
isSaving: state.isSaving,
|
||||
origPurchaseOrder: state.purchaseOrderState.map[purchaseOrder.id],
|
||||
purchaseOrder: purchaseOrder,
|
||||
company: state.company,
|
||||
onChanged: (InvoiceEntity purchaseOrder) {
|
||||
store.dispatch(UpdatePurchaseOrder(purchaseOrder));
|
||||
isSaving: state.isSaving,
|
||||
purchaseOrder: purchaseOrder,
|
||||
invoiceItemIndex: state.purchaseOrderUIState.editingItemIndex,
|
||||
origInvoice: store.state.purchaseOrderState.map[purchaseOrder.id],
|
||||
onSavePressed: (BuildContext context, [EntityAction action]) {
|
||||
Debouncer.runOnComplete(() {
|
||||
final purchaseOrder = store.state.purchaseOrderUIState.editing;
|
||||
final localization = navigatorKey.localization;
|
||||
final navigator = navigatorKey.currentState;
|
||||
if (purchaseOrder.clientId.isEmpty) {
|
||||
showDialog<ErrorDialog>(
|
||||
context: navigatorKey.currentContext,
|
||||
builder: (BuildContext context) {
|
||||
return ErrorDialog(localization.pleaseSelectAClient);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
if (purchaseOrder.isOld &&
|
||||
!hasPurchaseOrderChanges(
|
||||
purchaseOrder, state.purchaseOrderState.map) &&
|
||||
action != null &&
|
||||
action.isClientSide) {
|
||||
handleEntityAction(purchaseOrder, action);
|
||||
} else {
|
||||
final Completer<InvoiceEntity> completer =
|
||||
Completer<InvoiceEntity>();
|
||||
store.dispatch(SavePurchaseOrderRequest(
|
||||
completer: completer,
|
||||
purchaseOrder: purchaseOrder,
|
||||
action: action,
|
||||
));
|
||||
return completer.future.then((savedPurchaseOrder) {
|
||||
showToast(purchaseOrder.isNew
|
||||
? localization.createdPurchaseOrder
|
||||
: localization.updatedPurchaseOrder);
|
||||
|
||||
if (state.prefState.isMobile) {
|
||||
store.dispatch(
|
||||
UpdateCurrentRoute(PurchaseOrderViewScreen.route));
|
||||
if (purchaseOrder.isNew) {
|
||||
navigator.pushReplacementNamed(PurchaseOrderViewScreen.route);
|
||||
} else {
|
||||
navigator.pop(savedPurchaseOrder);
|
||||
}
|
||||
} else {
|
||||
if (!state.prefState.isPreviewVisible) {
|
||||
store.dispatch(TogglePreviewSidebar());
|
||||
}
|
||||
|
||||
viewEntity(entity: savedPurchaseOrder);
|
||||
|
||||
if (state.prefState.isEditorFullScreen(EntityType.invoice) &&
|
||||
state.prefState.editAfterSaving) {
|
||||
editEntity(entity: savedPurchaseOrder);
|
||||
}
|
||||
}
|
||||
|
||||
if (action != null && action.isClientSide) {
|
||||
handleEntityAction(savedPurchaseOrder, action);
|
||||
} else if (action != null && action.requiresSecondRequest) {
|
||||
handleEntityAction(savedPurchaseOrder, action);
|
||||
viewEntity(entity: savedPurchaseOrder, force: true);
|
||||
}
|
||||
}).catchError((Object error) {
|
||||
showDialog<ErrorDialog>(
|
||||
context: navigatorKey.currentContext,
|
||||
builder: (BuildContext context) {
|
||||
return ErrorDialog(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onItemsAdded: (items, clientId, projectId) {
|
||||
if (items.length == 1) {
|
||||
store.dispatch(EditPurchaseOrderItem(purchaseOrder.lineItems.length));
|
||||
}
|
||||
store.dispatch(AddPurchaseOrderItems(items));
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
createEntity(context: context, entity: InvoiceEntity(), force: true);
|
||||
if (state.purchaseOrderUIState.cancelCompleter != null) {
|
||||
state.purchaseOrderUIState.cancelCompleter.complete();
|
||||
if (['pdf', 'email'].contains(state.uiState.previousSubRoute)) {
|
||||
viewEntitiesByType(entityType: EntityType.purchaseOrder);
|
||||
} else {
|
||||
createEntity(context: context, entity: InvoiceEntity(), force: true);
|
||||
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||
}
|
||||
},
|
||||
onSavePressed: (BuildContext context) {
|
||||
Debouncer.runOnComplete(() {
|
||||
final purchaseOrder = store.state.purchaseOrderUIState.editing;
|
||||
final localization = AppLocalization.of(context);
|
||||
final Completer<InvoiceEntity> completer =
|
||||
new Completer<InvoiceEntity>();
|
||||
store.dispatch(SavePurchaseOrderRequest(
|
||||
completer: completer, purchaseOrder: purchaseOrder));
|
||||
return completer.future.then((savedPurchaseOrder) {
|
||||
showToast(purchaseOrder.isNew
|
||||
? localization.createdPurchaseOrder
|
||||
: localization.updatedPurchaseOrder);
|
||||
if (state.prefState.isMobile) {
|
||||
store.dispatch(UpdateCurrentRoute(PurchaseOrderViewScreen.route));
|
||||
if (purchaseOrder.isNew) {
|
||||
Navigator.of(context)
|
||||
.pushReplacementNamed(PurchaseOrderViewScreen.route);
|
||||
} else {
|
||||
Navigator.of(context).pop(savedPurchaseOrder);
|
||||
}
|
||||
} else {
|
||||
viewEntity(entity: savedPurchaseOrder, force: true);
|
||||
}
|
||||
}).catchError((Object error) {
|
||||
showDialog<ErrorDialog>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ErrorDialog(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final InvoiceEntity purchaseOrder;
|
||||
final CompanyEntity company;
|
||||
final Function(InvoiceEntity) onChanged;
|
||||
final Function(BuildContext) onSavePressed;
|
||||
final Function(BuildContext) onCancelPressed;
|
||||
final bool isLoading;
|
||||
final bool isSaving;
|
||||
final InvoiceEntity origPurchaseOrder;
|
||||
final AppState state;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue