Purchase orders

This commit is contained in:
Hillel Coren 2022-06-20 15:22:53 +03:00
parent 0807af8908
commit 7ed256e6bf
20 changed files with 373 additions and 90 deletions

View File

@ -209,7 +209,7 @@ abstract class InvoiceEntity extends Object
invitations: client == null
? BuiltList<InvitationEntity>()
: BuiltList(client.emailContacts
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList()),
updatedAt: 0,
archivedAt: 0,
@ -275,7 +275,8 @@ abstract class InvoiceEntity extends Object
(lineItem) => lineItem.typeId != InvoiceItemEntity.TYPE_UNPAID_FEE)
.toList())
..invitations.replace(invitations
.map((invitation) => InvitationEntity(contactId: invitation.contactId))
.map((invitation) =>
InvitationEntity(clientContactId: invitation.clientContactId))
.toList()));
InvoiceEntity applyClient(AppState state, ClientEntity client) {
@ -1193,7 +1194,7 @@ abstract class InvoiceEntity extends Object
InvitationEntity getInvitationForContact(ContactEntity contact) {
return invitations.firstWhere(
(invitation) => invitation.contactId == contact.id,
(invitation) => invitation.clientContactId == contact.id,
orElse: () => null);
}
@ -1579,11 +1580,15 @@ abstract class InvoiceItemEntity
abstract class InvitationEntity extends Object
with BaseEntity, SelectableEntity
implements Built<InvitationEntity, InvitationEntityBuilder> {
factory InvitationEntity({String contactId}) {
factory InvitationEntity({
String clientContactId,
String vendorContactId,
}) {
return _$InvitationEntity._(
id: BaseEntity.nextId,
isChanged: false,
contactId: contactId ?? '',
clientContactId: clientContactId ?? '',
vendorContactId: vendorContactId ?? '',
createdAt: 0,
key: '',
link: '',
@ -1611,7 +1616,10 @@ abstract class InvitationEntity extends Object
String get link;
@BuiltValueField(wireName: 'client_contact_id')
String get contactId;
String get clientContactId;
@BuiltValueField(wireName: 'vendor_contact_id')
String get vendorContactId;
@BuiltValueField(wireName: 'sent_date', compare: false)
String get sentDate;
@ -1662,6 +1670,11 @@ abstract class InvitationEntity extends Object
@override
FormatNumberType get listDisplayAmountType => FormatNumberType.money;
// ignore: unused_element
static void _initializeBuilder(InvitationEntityBuilder builder) => builder
..clientContactId = ''
..vendorContactId = '';
static Serializer<InvitationEntity> get serializer =>
_$invitationEntitySerializer;
}

View File

@ -935,7 +935,10 @@ class _$InvitationEntitySerializer
'link',
serializers.serialize(object.link, specifiedType: const FullType(String)),
'client_contact_id',
serializers.serialize(object.contactId,
serializers.serialize(object.clientContactId,
specifiedType: const FullType(String)),
'vendor_contact_id',
serializers.serialize(object.vendorContactId,
specifiedType: const FullType(String)),
'sent_date',
serializers.serialize(object.sentDate,
@ -1025,7 +1028,11 @@ class _$InvitationEntitySerializer
specifiedType: const FullType(String)) as String;
break;
case 'client_contact_id':
result.contactId = serializers.deserialize(value,
result.clientContactId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'vendor_contact_id':
result.vendorContactId = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
case 'sent_date':
@ -2806,7 +2813,9 @@ class _$InvitationEntity extends InvitationEntity {
@override
final String link;
@override
final String contactId;
final String clientContactId;
@override
final String vendorContactId;
@override
final String sentDate;
@override
@ -2841,7 +2850,8 @@ class _$InvitationEntity extends InvitationEntity {
_$InvitationEntity._(
{this.key,
this.link,
this.contactId,
this.clientContactId,
this.vendorContactId,
this.sentDate,
this.viewedDate,
this.openedDate,
@ -2859,7 +2869,9 @@ class _$InvitationEntity extends InvitationEntity {
BuiltValueNullFieldError.checkNotNull(key, 'InvitationEntity', 'key');
BuiltValueNullFieldError.checkNotNull(link, 'InvitationEntity', 'link');
BuiltValueNullFieldError.checkNotNull(
contactId, 'InvitationEntity', 'contactId');
clientContactId, 'InvitationEntity', 'clientContactId');
BuiltValueNullFieldError.checkNotNull(
vendorContactId, 'InvitationEntity', 'vendorContactId');
BuiltValueNullFieldError.checkNotNull(
sentDate, 'InvitationEntity', 'sentDate');
BuiltValueNullFieldError.checkNotNull(
@ -2889,7 +2901,8 @@ class _$InvitationEntity extends InvitationEntity {
return other is InvitationEntity &&
key == other.key &&
link == other.link &&
contactId == other.contactId &&
clientContactId == other.clientContactId &&
vendorContactId == other.vendorContactId &&
isChanged == other.isChanged &&
createdAt == other.createdAt &&
updatedAt == other.updatedAt &&
@ -2912,11 +2925,13 @@ class _$InvitationEntity extends InvitationEntity {
$jc(
$jc(
$jc(
$jc(
$jc(
$jc(
$jc($jc(0, key.hashCode),
link.hashCode),
contactId.hashCode),
clientContactId.hashCode),
vendorContactId.hashCode),
isChanged.hashCode),
createdAt.hashCode),
updatedAt.hashCode),
@ -2933,7 +2948,8 @@ class _$InvitationEntity extends InvitationEntity {
return (newBuiltValueToStringHelper('InvitationEntity')
..add('key', key)
..add('link', link)
..add('contactId', contactId)
..add('clientContactId', clientContactId)
..add('vendorContactId', vendorContactId)
..add('sentDate', sentDate)
..add('viewedDate', viewedDate)
..add('openedDate', openedDate)
@ -2963,9 +2979,15 @@ class InvitationEntityBuilder
String get link => _$this._link;
set link(String link) => _$this._link = link;
String _contactId;
String get contactId => _$this._contactId;
set contactId(String contactId) => _$this._contactId = contactId;
String _clientContactId;
String get clientContactId => _$this._clientContactId;
set clientContactId(String clientContactId) =>
_$this._clientContactId = clientContactId;
String _vendorContactId;
String get vendorContactId => _$this._vendorContactId;
set vendorContactId(String vendorContactId) =>
_$this._vendorContactId = vendorContactId;
String _sentDate;
String get sentDate => _$this._sentDate;
@ -3021,14 +3043,17 @@ class InvitationEntityBuilder
String get id => _$this._id;
set id(String id) => _$this._id = id;
InvitationEntityBuilder();
InvitationEntityBuilder() {
InvitationEntity._initializeBuilder(this);
}
InvitationEntityBuilder get _$this {
final $v = _$v;
if ($v != null) {
_key = $v.key;
_link = $v.link;
_contactId = $v.contactId;
_clientContactId = $v.clientContactId;
_vendorContactId = $v.vendorContactId;
_sentDate = $v.sentDate;
_viewedDate = $v.viewedDate;
_openedDate = $v.openedDate;
@ -3066,8 +3091,10 @@ class InvitationEntityBuilder
key, 'InvitationEntity', 'key'),
link: BuiltValueNullFieldError.checkNotNull(
link, 'InvitationEntity', 'link'),
contactId: BuiltValueNullFieldError.checkNotNull(
contactId, 'InvitationEntity', 'contactId'),
clientContactId: BuiltValueNullFieldError.checkNotNull(
clientContactId, 'InvitationEntity', 'clientContactId'),
vendorContactId: BuiltValueNullFieldError.checkNotNull(
vendorContactId, 'InvitationEntity', 'vendorContactId'),
sentDate: BuiltValueNullFieldError.checkNotNull(
sentDate, 'InvitationEntity', 'sentDate'),
viewedDate: BuiltValueNullFieldError.checkNotNull(
@ -3078,10 +3105,9 @@ class InvitationEntityBuilder
isChanged: isChanged,
createdAt: BuiltValueNullFieldError.checkNotNull(
createdAt, 'InvitationEntity', 'createdAt'),
updatedAt: BuiltValueNullFieldError.checkNotNull(
updatedAt, 'InvitationEntity', 'updatedAt'),
archivedAt: BuiltValueNullFieldError.checkNotNull(
archivedAt, 'InvitationEntity', 'archivedAt'),
updatedAt:
BuiltValueNullFieldError.checkNotNull(updatedAt, 'InvitationEntity', 'updatedAt'),
archivedAt: BuiltValueNullFieldError.checkNotNull(archivedAt, 'InvitationEntity', 'archivedAt'),
isDeleted: isDeleted,
createdUserId: createdUserId,
assignedUserId: assignedUserId,

View File

@ -438,6 +438,12 @@ abstract class VendorEntity extends Object
}
}
List<VendorContactEntity> get emailContacts {
//final list = contacts.where((contact) => contact.sendEmail).toList();
final list = contacts.where((contact) => true).toList();
return list.isEmpty ? [primaryContact] : list;
}
VendorContactEntity get primaryContact =>
contacts.firstWhere((contact) => contact.isPrimary,
orElse: () => VendorContactEntity());

View File

@ -118,7 +118,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
..isChanged = true
..clientId = client?.id ?? ''
..invitations.replace((client?.emailContacts ?? <ContactEntity>[])
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList()));
}),
TypedReducer<InvoiceEntity, RestoreCreditsSuccess>((credits, action) {
@ -137,8 +137,8 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
TypedReducer<InvoiceEntity, AddCreditContact>((invoice, action) {
return invoice.rebuild((b) => b
..invitations.add(
action.invitation ?? InvitationEntity(contactId: action.contact.id)));
..invitations.add(action.invitation ??
InvitationEntity(clientContactId: action.contact.id)));
}),
TypedReducer<InvoiceEntity, RemoveCreditContact>((invoice, action) {
return invoice.rebuild((b) => b..invitations.remove(action.invitation));

View File

@ -8,8 +8,9 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
ContactEntity creditContactSelector(InvoiceEntity credit, ClientEntity client) {
var contactIds =
credit.invitations.map((invitation) => invitation.contactId).toList();
var contactIds = credit.invitations
.map((invitation) => invitation.clientContactId)
.toList();
if (contactIds.contains(client.primaryContact.id)) {
contactIds = [client.primaryContact.id];
}

View File

@ -122,7 +122,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
..isChanged = true
..clientId = client?.id ?? ''
..invitations.replace((client?.emailContacts ?? <ContactEntity>[])
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList()));
}),
TypedReducer<InvoiceEntity, RestoreInvoicesSuccess>((invoices, action) {
@ -141,8 +141,8 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
TypedReducer<InvoiceEntity, AddInvoiceContact>((invoice, action) {
return invoice.rebuild((b) => b
..invitations.add(
action.invitation ?? InvitationEntity(contactId: action.contact.id)));
..invitations.add(action.invitation ??
InvitationEntity(clientContactId: action.contact.id)));
}),
TypedReducer<InvoiceEntity, RemoveInvoiceContact>((invoice, action) {
return invoice.rebuild((b) => b..invitations.remove(action.invitation));

View File

@ -20,8 +20,9 @@ InvoiceEntity invoiceQuoteSelector(
ContactEntity invoiceContactSelector(
InvoiceEntity invoice, ClientEntity client) {
var contactIds =
invoice.invitations.map((invitation) => invitation.contactId).toList();
var contactIds = invoice.invitations
.map((invitation) => invitation.clientContactId)
.toList();
if (contactIds.contains(client.primaryContact.id)) {
contactIds = [client.primaryContact.id];
}

View File

@ -29,11 +29,13 @@ class EditPurchaseOrder implements PersistUI, PersistPrefs {
EditPurchaseOrder(
{@required this.purchaseOrder,
this.completer,
this.purchaseOrderItemIndex,
this.cancelCompleter,
this.force = false});
final InvoiceEntity purchaseOrder;
final Completer completer;
final int purchaseOrderItemIndex;
final Completer cancelCompleter;
final bool force;
}
@ -66,6 +68,12 @@ class UpdatePurchaseOrder implements PersistUI {
final InvoiceEntity purchaseOrder;
}
class UpdatePurchaseOrderVendor implements PersistUI {
UpdatePurchaseOrderVendor({this.vendor});
final VendorEntity vendor;
}
class LoadPurchaseOrder {
LoadPurchaseOrder({this.completer, this.purchaseOrderId});
@ -237,9 +245,9 @@ class EmailPurchaseOrderRequest implements StartSaving {
}
class EmailPurchaseOrderSuccess implements StopSaving, PersistData {
EmailPurchaseOrderSuccess(this.quote);
EmailPurchaseOrderSuccess(this.purchaseOrder);
final InvoiceEntity quote;
final InvoiceEntity purchaseOrder;
}
class EmailPurchaseOrderFailure implements StopSaving {
@ -248,6 +256,44 @@ class EmailPurchaseOrderFailure implements StopSaving {
final dynamic error;
}
class MarkSentPurchaseOrdersRequest implements StartSaving {
MarkSentPurchaseOrdersRequest(this.completer, this.purchaseOrderIds);
final Completer completer;
final List<String> purchaseOrderIds;
}
class MarkSentPurchaseOrderSuccess implements StopSaving, PersistData {
MarkSentPurchaseOrderSuccess(this.purchaseOrders);
final List<InvoiceEntity> purchaseOrders;
}
class MarkSentPurchaseOrderFailure implements StopSaving {
MarkSentPurchaseOrderFailure(this.error);
final Object error;
}
class ApprovePurchaseOrders implements StartSaving {
ApprovePurchaseOrders(this.completer, this.purchaseOrderIds);
final List<String> purchaseOrderIds;
final Completer completer;
}
class ApprovePurchaseOrderSuccess implements StopSaving {
ApprovePurchaseOrderSuccess({this.purchaseOrders});
final List<InvoiceEntity> purchaseOrders;
}
class ApprovePurchaseOrderFailure implements StopSaving {
ApprovePurchaseOrderFailure(this.error);
final dynamic error;
}
class AddPurchaseOrderContact implements PersistUI {
AddPurchaseOrderContact({this.contact, this.invitation});
@ -314,6 +360,18 @@ class FilterPurchaseOrdersByState implements PersistUI {
final EntityState state;
}
class FilterPurchaseOrdersByStatus implements PersistUI {
FilterPurchaseOrdersByStatus(this.status);
final EntityStatus status;
}
class FilterPurchaseOrderDropdown {
FilterPurchaseOrderDropdown(this.filter);
final String filter;
}
class FilterPurchaseOrdersByCustom1 implements PersistUI {
FilterPurchaseOrdersByCustom1(this.value);

View File

@ -1,21 +1,28 @@
import 'package:redux/redux.dart';
// Package imports:
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:redux/redux.dart';
// Project imports:
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart';
import 'package:invoiceninja_flutter/redux/purchase_order/purchase_order_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
import 'package:invoiceninja_flutter/redux/purchase_order/purchase_order_state.dart';
import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
EntityUIState purchaseOrderUIReducer(
PurchaseOrderUIState state, dynamic action) {
return state.rebuild((b) => b
..listUIState.replace(purchaseOrderListReducer(state.listUIState, action))
..listUIState
.replace(purchaseOrderListReducer(state.listUIState, action))
..editing.replace(editingReducer(state.editing, action))
..editingItemIndex = editingItemReducer(state.editingItemIndex, action)
..selectedId = selectedIdReducer(state.selectedId, action)
..forceSelected = forceSelectedReducer(state.forceSelected, action)
..tabIndex = tabIndexReducer(state.tabIndex, action));
..tabIndex = tabIndexReducer(state.tabIndex, action)
//..historyActivityId = historyActivityIdReducer(state.historyActivityId, action)
);
}
final forceSelectedReducer = combineReducers<bool>([
@ -42,6 +49,27 @@ final tabIndexReducer = combineReducers<int>([
}),
]);
final historyActivityIdReducer = combineReducers<String>([
TypedReducer<String, ShowPdfPurchaseOrder>(
(index, action) => action.activityId),
]);
final editingItemReducer = combineReducers<int>([
TypedReducer<int, EditPurchaseOrder>(
(index, action) => action.purchaseOrderItemIndex),
TypedReducer<int, EditPurchaseOrderItem>((index, action) => action.itemIndex),
]);
Reducer<String> dropdownFilterReducer = combineReducers([
TypedReducer<String, FilterPurchaseOrderDropdown>(
filterpurchaseOrderDropdownReducer),
]);
String filterpurchaseOrderDropdownReducer(
String dropdownFilter, FilterPurchaseOrderDropdown action) {
return action.filter;
}
Reducer<String> selectedIdReducer = combineReducers([
TypedReducer<String, ArchivePurchaseOrdersSuccess>((completer, action) => ''),
TypedReducer<String, DeletePurchaseOrdersSuccess>((completer, action) => ''),
@ -50,15 +78,21 @@ Reducer<String> selectedIdReducer = combineReducers([
? action.entityId
: selectedId),
TypedReducer<String, ViewPurchaseOrder>(
(String selectedId, dynamic action) => action.purchaseOrderId),
(selectedId, action) => action.purchaseOrderId),
TypedReducer<String, AddPurchaseOrderSuccess>(
(String selectedId, dynamic action) => action.purchaseOrder.id),
(selectedId, action) => action.purchaseOrder.id),
TypedReducer<String, ShowEmailPurchaseOrder>(
(selectedId, action) => action.purchaseOrder.id),
TypedReducer<String, ShowPdfPurchaseOrder>(
(selectedId, action) => action.purchaseOrder.id),
TypedReducer<String, SelectCompany>(
(selectedId, action) => action.clearSelection ? '' : selectedId),
TypedReducer<String, ClearEntityFilter>((selectedId, action) => ''),
TypedReducer<String, SortPurchaseOrders>((selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrders>((selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrdersByState>((selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrdersByStatus>(
(selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrdersByCustom1>(
(selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrdersByCustom2>(
@ -67,6 +101,8 @@ Reducer<String> selectedIdReducer = combineReducers([
(selectedId, action) => ''),
TypedReducer<String, FilterPurchaseOrdersByCustom4>(
(selectedId, action) => ''),
TypedReducer<String, ClearEntitySelection>((selectedId, action) =>
action.entityType == EntityType.purchaseOrder ? '' : selectedId),
TypedReducer<String, FilterByEntity>(
(selectedId, action) => action.clearSelection
? ''
@ -78,6 +114,32 @@ Reducer<String> selectedIdReducer = combineReducers([
final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, SavePurchaseOrderSuccess>(_updateEditing),
TypedReducer<InvoiceEntity, AddPurchaseOrderSuccess>(_updateEditing),
TypedReducer<InvoiceEntity, EditPurchaseOrder>(_updateEditing),
TypedReducer<InvoiceEntity, UpdatePurchaseOrder>((purchaseOrder, action) {
return action.purchaseOrder.rebuild((b) => b..isChanged = true);
}),
TypedReducer<InvoiceEntity, AddPurchaseOrderItem>((invoice, action) {
return invoice.rebuild((b) => b..isChanged = true);
}),
TypedReducer<InvoiceEntity, MovePurchaseOrderItem>((invoice, action) {
return invoice.moveLineItem(action.oldIndex, action.newIndex);
}),
TypedReducer<InvoiceEntity, DeletePurchaseOrderItem>((invoice, action) {
return invoice.rebuild((b) => b..isChanged = true);
}),
TypedReducer<InvoiceEntity, UpdatePurchaseOrderItem>((invoice, action) {
return invoice.rebuild((b) => b..isChanged = true);
}),
TypedReducer<InvoiceEntity, UpdatePurchaseOrderVendor>(
(purchaseOrder, action) {
final vendor = action.vendor;
return purchaseOrder.rebuild((b) => b
..isChanged = true
..vendorId = vendor?.id ?? ''
..invitations.replace((vendor?.emailContacts ?? <VendorContactEntity>[])
.map((contact) => InvitationEntity(vendorContactId: contact.id))
.toList()));
}),
TypedReducer<InvoiceEntity, RestorePurchaseOrdersSuccess>(
(purchaseOrders, action) {
return action.purchaseOrders[0];
@ -90,11 +152,21 @@ final editingReducer = combineReducers<InvoiceEntity>([
(purchaseOrders, action) {
return action.purchaseOrders[0];
}),
TypedReducer<InvoiceEntity, EditPurchaseOrder>(_updateEditing),
TypedReducer<InvoiceEntity, UpdatePurchaseOrder>((purchaseOrder, action) {
return action.purchaseOrder.rebuild((b) => b..isChanged = true);
}),
TypedReducer<InvoiceEntity, AddPurchaseOrderItem>(_addPurchaseOrderItem),
TypedReducer<InvoiceEntity, AddPurchaseOrderItems>(_addPurchaseOrderItems),
TypedReducer<InvoiceEntity, DeletePurchaseOrderItem>(
_removePurchaseOrderItem),
TypedReducer<InvoiceEntity, UpdatePurchaseOrderItem>(
_updatePurchaseOrderItem),
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
TypedReducer<InvoiceEntity, AddPurchaseOrderContact>((invoice, action) {
return invoice.rebuild((b) => b
..invitations.add(action.invitation ??
InvitationEntity(clientContactId: action.contact.id)));
}),
TypedReducer<InvoiceEntity, RemovePurchaseOrderContact>((invoice, action) {
return invoice.rebuild((b) => b..invitations.remove(action.invitation));
}),
]);
InvoiceEntity _clearEditing(InvoiceEntity purchaseOrder, dynamic action) {
@ -105,15 +177,49 @@ InvoiceEntity _updateEditing(InvoiceEntity purchaseOrder, dynamic action) {
return action.purchaseOrder;
}
InvoiceEntity _addPurchaseOrderItem(
InvoiceEntity purchaseOrder, AddPurchaseOrderItem action) {
return purchaseOrder.rebuild(
(b) => b..lineItems.add(action.purchaseOrderItem ?? InvoiceItemEntity()));
}
InvoiceEntity _addPurchaseOrderItems(
InvoiceEntity purchaseOrder, AddPurchaseOrderItems action) {
return purchaseOrder.rebuild((b) => b..lineItems.addAll(action.lineItems));
}
InvoiceEntity _removePurchaseOrderItem(
InvoiceEntity purchaseOrder, DeletePurchaseOrderItem action) {
if (purchaseOrder.lineItems.length <= action.index) {
return purchaseOrder;
}
return purchaseOrder.rebuild((b) => b..lineItems.removeAt(action.index));
}
InvoiceEntity _updatePurchaseOrderItem(
InvoiceEntity purchaseOrder, UpdatePurchaseOrderItem action) {
if (purchaseOrder.lineItems.length <= action.index) {
return purchaseOrder;
}
return purchaseOrder
.rebuild((b) => b..lineItems[action.index] = action.purchaseOrderItem);
}
final purchaseOrderListReducer = combineReducers<ListUIState>([
TypedReducer<ListUIState, SortPurchaseOrders>(_sortPurchaseOrders),
TypedReducer<ListUIState, FilterPurchaseOrdersByState>(
_filterPurchaseOrdersByState),
TypedReducer<ListUIState, FilterPurchaseOrdersByStatus>(
_filterPurchaseOrdersByStatus),
TypedReducer<ListUIState, FilterPurchaseOrders>(_filterPurchaseOrders),
TypedReducer<ListUIState, FilterPurchaseOrdersByCustom1>(
_filterPurchaseOrdersByCustom1),
TypedReducer<ListUIState, FilterPurchaseOrdersByCustom2>(
_filterPurchaseOrdersByCustom2),
TypedReducer<ListUIState, FilterPurchaseOrdersByCustom3>(
_filterPurchaseOrdersByCustom3),
TypedReducer<ListUIState, FilterPurchaseOrdersByCustom4>(
_filterPurchaseOrdersByCustom4),
TypedReducer<ListUIState, StartPurchaseOrderMultiselect>(
_startListMultiselect),
TypedReducer<ListUIState, AddToPurchaseOrderMultiselect>(
@ -155,6 +261,28 @@ ListUIState _filterPurchaseOrdersByCustom2(
}
}
ListUIState _filterPurchaseOrdersByCustom3(
ListUIState purchaseOrderListState, FilterPurchaseOrdersByCustom3 action) {
if (purchaseOrderListState.custom3Filters.contains(action.value)) {
return purchaseOrderListState
.rebuild((b) => b..custom3Filters.remove(action.value));
} else {
return purchaseOrderListState
.rebuild((b) => b..custom3Filters.add(action.value));
}
}
ListUIState _filterPurchaseOrdersByCustom4(
ListUIState purchaseOrderListState, FilterPurchaseOrdersByCustom4 action) {
if (purchaseOrderListState.custom4Filters.contains(action.value)) {
return purchaseOrderListState
.rebuild((b) => b..custom4Filters.remove(action.value));
} else {
return purchaseOrderListState
.rebuild((b) => b..custom4Filters.add(action.value));
}
}
ListUIState _filterPurchaseOrdersByState(
ListUIState purchaseOrderListState, FilterPurchaseOrdersByState action) {
if (purchaseOrderListState.stateFilters.contains(action.state)) {
@ -166,6 +294,17 @@ ListUIState _filterPurchaseOrdersByState(
}
}
ListUIState _filterPurchaseOrdersByStatus(
ListUIState purchaseOrderListState, FilterPurchaseOrdersByStatus action) {
if (purchaseOrderListState.statusFilters.contains(action.status)) {
return purchaseOrderListState
.rebuild((b) => b..statusFilters.remove(action.status));
} else {
return purchaseOrderListState
.rebuild((b) => b..statusFilters.add(action.status));
}
}
ListUIState _filterPurchaseOrders(
ListUIState purchaseOrderListState, FilterPurchaseOrders action) {
return purchaseOrderListState.rebuild((b) => b
@ -183,24 +322,25 @@ ListUIState _sortPurchaseOrders(
}
ListUIState _startListMultiselect(
ListUIState productListState, StartPurchaseOrderMultiselect action) {
return productListState.rebuild((b) => b..selectedIds = ListBuilder());
ListUIState purchaseOrderListState, StartPurchaseOrderMultiselect action) {
return purchaseOrderListState.rebuild((b) => b..selectedIds = ListBuilder());
}
ListUIState _addToListMultiselect(
ListUIState productListState, AddToPurchaseOrderMultiselect action) {
return productListState.rebuild((b) => b..selectedIds.add(action.entity.id));
ListUIState purchaseOrderListState, AddToPurchaseOrderMultiselect action) {
return purchaseOrderListState
.rebuild((b) => b..selectedIds.add(action.entity.id));
}
ListUIState _removeFromListMultiselect(
ListUIState productListState, RemoveFromPurchaseOrderMultiselect action) {
return productListState
ListUIState _removeFromListMultiselect(ListUIState purchaseOrderListState,
RemoveFromPurchaseOrderMultiselect action) {
return purchaseOrderListState
.rebuild((b) => b..selectedIds.remove(action.entity.id));
}
ListUIState _clearListMultiselect(
ListUIState productListState, ClearPurchaseOrderMultiselect action) {
return productListState.rebuild((b) => b..selectedIds = null);
ListUIState purchaseOrderListState, ClearPurchaseOrderMultiselect action) {
return purchaseOrderListState.rebuild((b) => b..selectedIds = null);
}
final purchaseOrdersReducer = combineReducers<PurchaseOrderState>([
@ -210,16 +350,33 @@ final purchaseOrdersReducer = combineReducers<PurchaseOrderState>([
TypedReducer<PurchaseOrderState, LoadPurchaseOrdersSuccess>(
_setLoadedPurchaseOrders),
TypedReducer<PurchaseOrderState, LoadPurchaseOrderSuccess>(
_setLoadedPurchaseOrder),
_updatePurchaseOrder),
TypedReducer<PurchaseOrderState, LoadCompanySuccess>(_setLoadedCompany),
TypedReducer<PurchaseOrderState, MarkSentPurchaseOrderSuccess>(
_markSentPurchaseOrderSuccess),
TypedReducer<PurchaseOrderState, EmailPurchaseOrderSuccess>(
_emailPurchaseOrderSuccess),
TypedReducer<PurchaseOrderState, ArchivePurchaseOrdersSuccess>(
_archivePurchaseOrderSuccess),
TypedReducer<PurchaseOrderState, DeletePurchaseOrdersSuccess>(
_deletePurchaseOrderSuccess),
TypedReducer<PurchaseOrderState, RestorePurchaseOrdersSuccess>(
_restorePurchaseOrderSuccess),
TypedReducer<PurchaseOrderState, ApprovePurchaseOrderSuccess>(
_approvePurchaseOrderSuccess),
]);
PurchaseOrderState _markSentPurchaseOrderSuccess(
PurchaseOrderState purchaseOrderState,
MarkSentPurchaseOrderSuccess action) {
final purchaseOrderMap = Map<String, InvoiceEntity>.fromIterable(
action.purchaseOrders,
key: (dynamic item) => item.id,
value: (dynamic item) => item,
);
return purchaseOrderState.rebuild((b) => b..map.addAll(purchaseOrderMap));
}
PurchaseOrderState _archivePurchaseOrderSuccess(
PurchaseOrderState purchaseOrderState,
ArchivePurchaseOrdersSuccess action) {
@ -249,23 +406,36 @@ PurchaseOrderState _restorePurchaseOrderSuccess(
});
}
PurchaseOrderState _emailPurchaseOrderSuccess(
PurchaseOrderState purchaseOrderState, EmailPurchaseOrderSuccess action) {
return purchaseOrderState
.rebuild((b) => b..map[action.purchaseOrder.id] = action.purchaseOrder);
}
PurchaseOrderState _approvePurchaseOrderSuccess(
PurchaseOrderState purchaseOrderState, ApprovePurchaseOrderSuccess action) {
final purchaseOrderMap = Map<String, InvoiceEntity>.fromIterable(
action.purchaseOrders,
key: (dynamic item) => item.id,
value: (dynamic item) => item,
);
return purchaseOrderState.rebuild((b) => b..map.addAll(purchaseOrderMap));
}
PurchaseOrderState _addPurchaseOrder(
PurchaseOrderState purchaseOrderState, AddPurchaseOrderSuccess action) {
return purchaseOrderState.rebuild((b) => b
..map[action.purchaseOrder.id] = action.purchaseOrder
.rebuild((b) => b..loadedAt = DateTime.now().millisecondsSinceEpoch)
..list.add(action.purchaseOrder.id));
}
PurchaseOrderState _updatePurchaseOrder(
PurchaseOrderState purchaseOrderState, SavePurchaseOrderSuccess action) {
return purchaseOrderState
.rebuild((b) => b..map[action.purchaseOrder.id] = action.purchaseOrder);
}
PurchaseOrderState _setLoadedPurchaseOrder(
PurchaseOrderState purchaseOrderState, LoadPurchaseOrderSuccess action) {
return purchaseOrderState
.rebuild((b) => b..map[action.purchaseOrder.id] = action.purchaseOrder);
PurchaseOrderState invoiceState, dynamic action) {
final InvoiceEntity purchaseOrder = action.purchaseOrder;
return invoiceState.rebuild((b) => b
..map[purchaseOrder.id] = purchaseOrder
.rebuild((b) => b..loadedAt = DateTime.now().millisecondsSinceEpoch));
}
PurchaseOrderState _setLoadedPurchaseOrders(

View File

@ -119,7 +119,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
..isChanged = true
..clientId = client?.id ?? ''
..invitations.replace((client?.emailContacts ?? <ContactEntity>[])
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList()));
}),
TypedReducer<InvoiceEntity, RestoreQuotesSuccess>((quotes, action) {
@ -138,8 +138,8 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
TypedReducer<InvoiceEntity, AddQuoteContact>((invoice, action) {
return invoice.rebuild((b) => b
..invitations.add(
action.invitation ?? InvitationEntity(contactId: action.contact.id)));
..invitations.add(action.invitation ??
InvitationEntity(clientContactId: action.contact.id)));
}),
TypedReducer<InvoiceEntity, RemoveQuoteContact>((invoice, action) {
return invoice.rebuild((b) => b..invitations.remove(action.invitation));
@ -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));

View File

@ -13,8 +13,9 @@ ClientEntity quoteClientSelector(
}
ContactEntity quoteContactSelector(InvoiceEntity quote, ClientEntity client) {
var contactIds =
quote.invitations.map((invitation) => invitation.contactId).toList();
var contactIds = quote.invitations
.map((invitation) => invitation.clientContactId)
.toList();
if (contactIds.contains(client.primaryContact.id)) {
contactIds = [client.primaryContact.id];
}

View File

@ -145,7 +145,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
..isChanged = true
..clientId = client?.id ?? ''
..invitations.replace((client?.emailContacts ?? <ContactEntity>[])
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList()));
}),
TypedReducer<InvoiceEntity, RestoreRecurringInvoicesSuccess>(
@ -172,8 +172,8 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, AddRecurringInvoiceContact>(
(recurringInvoice, action) {
return recurringInvoice.rebuild((b) => b
..invitations.add(
action.invitation ?? InvitationEntity(contactId: action.contact.id)));
..invitations.add(action.invitation ??
InvitationEntity(clientContactId: action.contact.id)));
}),
TypedReducer<InvoiceEntity, RemoveRecurringInvoiceContact>(
(recurringInvoice, action) {

View File

@ -177,7 +177,7 @@ class _InvoiceEmailViewState extends State<InvoiceEmailView>
final settings = getClientSettings(state, client);
final contacts = invoice.invitations
.map((invitation) => client.contacts.firstWhere(
(contact) => contact.id == invitation.contactId,
(contact) => contact.id == invitation.clientContactId,
orElse: () => null))
.toList();

View File

@ -43,6 +43,7 @@ import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_contacts_vm.da
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_details_vm.dart';
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_items_vm.dart';
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/purchase_order/edit/purchase_order_edit_items_vm.dart';
import 'package:invoiceninja_flutter/ui/quote/edit/quote_edit_items_vm.dart';
import 'package:invoiceninja_flutter/ui/recurring_invoice/edit/recurring_invoice_edit_items_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
@ -568,6 +569,10 @@ class InvoiceEditDesktopState extends State<InvoiceEditDesktop>
viewModel: widget.entityViewModel,
isTasks: _showTasksTable,
)
else if (entityType == EntityType.purchaseOrder)
PurchaseOrderEditItemsScreen(
viewModel: widget.entityViewModel,
)
else
SizedBox(),
Row(

View File

@ -203,7 +203,7 @@ class InvoiceEditVM extends AbstractInvoiceEditVM {
..projectId = projectId ?? ''
..invitations.replace(BuiltList<InvitationEntity>(client
.emailContacts
.map((contact) => InvitationEntity(contactId: contact.id))
.map((contact) => InvitationEntity(clientContactId: contact.id))
.toList())))));
}
store.dispatch(AddInvoiceItems(items));

View File

@ -46,7 +46,7 @@ class _InvitationListTile extends StatelessWidget {
final state = viewModel.state;
final client = state.clientState.get(viewModel.invoice.clientId);
final contact = client.contacts.firstWhere(
(contact) => contact.id == invitation.contactId,
(contact) => contact.id == invitation.clientContactId,
orElse: () => ContactEntity());
if (contact.isNew) {

View File

@ -132,7 +132,7 @@ ReportResult creditReport(
continue;
}
final contact = client.getContact(credit.invitations.first.contactId);
final contact = client.getContact(credit.invitations.first.clientContactId);
if (credit.isDeleted || client.isDeleted) {
continue;

View File

@ -160,7 +160,8 @@ ReportResult invoiceReport(
continue;
}
final contact = client.getContact(invoice.invitations.first.contactId);
final contact =
client.getContact(invoice.invitations.first.clientContactId);
if (invoice.isDeleted || client.isDeleted) {
continue;

View File

@ -130,7 +130,7 @@ ReportResult quoteReport(
continue;
}
final contact = client.getContact(quote.invitations.first.contactId);
final contact = client.getContact(quote.invitations.first.clientContactId);
//final vendor = vendorMap[quote.vendorId];
if (quote.isDeleted || client.isDeleted) {

View File

@ -152,7 +152,8 @@ ReportResult recurringInvoiceReport(
continue;
}
final contact = client.getContact(invoice.invitations.first.contactId);
final contact =
client.getContact(invoice.invitations.first.clientContactId);
if (invoice.isDeleted || client.isDeleted) {
continue;