Recurring invoices
This commit is contained in:
parent
8ddc039897
commit
27f142e75d
|
|
@ -146,6 +146,14 @@ List<String> filteredInvoicesSelector(
|
|||
!invoiceListState.custom2Filters.contains(invoice.customValue2)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom3Filters.isNotEmpty &&
|
||||
!invoiceListState.custom3Filters.contains(invoice.customValue3)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom4Filters.isNotEmpty &&
|
||||
!invoiceListState.custom4Filters.contains(invoice.customValue4)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,31 +32,55 @@ List<String> filteredRecurringInvoicesSelector(
|
|||
BuiltMap<String, InvoiceEntity> recurringInvoiceMap,
|
||||
BuiltMap<String, ClientEntity> clientMap,
|
||||
BuiltList<String> recurringInvoiceList,
|
||||
ListUIState recurringInvoiceListState,
|
||||
ListUIState invoiceListState,
|
||||
StaticState staticState,
|
||||
BuiltMap<String, UserEntity> userMap,
|
||||
) {
|
||||
final list = recurringInvoiceList.where((recurringInvoiceId) {
|
||||
final recurringInvoice = recurringInvoiceMap[recurringInvoiceId];
|
||||
if (filterEntityId != null && recurringInvoice.id != filterEntityId) {
|
||||
return false;
|
||||
} else {}
|
||||
final invoice = recurringInvoiceMap[recurringInvoiceId];
|
||||
final client =
|
||||
clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId);
|
||||
|
||||
if (!recurringInvoice
|
||||
.matchesStates(recurringInvoiceListState.stateFilters)) {
|
||||
if (!client.isActive &&
|
||||
!client.matchesEntityFilter(filterEntityType, filterEntityId)) {
|
||||
return false;
|
||||
}
|
||||
if (recurringInvoiceListState.custom1Filters.isNotEmpty &&
|
||||
!recurringInvoiceListState.custom1Filters
|
||||
.contains(recurringInvoice.customValue1)) {
|
||||
|
||||
if (filterEntityType == EntityType.client && client.id != filterEntityId) {
|
||||
return false;
|
||||
} else if (filterEntityType == EntityType.user &&
|
||||
invoice.assignedUserId != filterEntityId) {
|
||||
return false;
|
||||
}
|
||||
if (recurringInvoiceListState.custom2Filters.isNotEmpty &&
|
||||
!recurringInvoiceListState.custom2Filters
|
||||
.contains(recurringInvoice.customValue2)) {
|
||||
|
||||
if (!invoice.matchesStates(invoiceListState.stateFilters)) {
|
||||
return false;
|
||||
}
|
||||
return recurringInvoice.matchesFilter(recurringInvoiceListState.filter);
|
||||
if (!invoice.matchesStatuses(invoiceListState.statusFilters)) {
|
||||
return false;
|
||||
}
|
||||
if (!invoice.matchesFilter(invoiceListState.filter) &&
|
||||
!client.matchesFilter(invoiceListState.filter)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom1Filters.isNotEmpty &&
|
||||
!invoiceListState.custom1Filters.contains(invoice.customValue1)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom2Filters.isNotEmpty &&
|
||||
!invoiceListState.custom2Filters.contains(invoice.customValue2)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom3Filters.isNotEmpty &&
|
||||
!invoiceListState.custom3Filters.contains(invoice.customValue3)) {
|
||||
return false;
|
||||
}
|
||||
if (invoiceListState.custom4Filters.isNotEmpty &&
|
||||
!invoiceListState.custom4Filters.contains(invoice.customValue4)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}).toList();
|
||||
|
||||
list.sort((recurringInvoiceAId, recurringInvoiceBId) {
|
||||
|
|
@ -65,8 +89,8 @@ List<String> filteredRecurringInvoicesSelector(
|
|||
|
||||
return recurringInvoiceA.compareTo(
|
||||
invoice: recurringInvoiceB,
|
||||
sortField: recurringInvoiceListState.sortField,
|
||||
sortAscending: recurringInvoiceListState.sortAscending,
|
||||
sortField: invoiceListState.sortField,
|
||||
sortAscending: invoiceListState.sortAscending,
|
||||
clientMap: clientMap,
|
||||
staticState: staticState,
|
||||
userMap: userMap,
|
||||
|
|
@ -76,8 +100,52 @@ List<String> filteredRecurringInvoicesSelector(
|
|||
return list;
|
||||
}
|
||||
|
||||
var memoizedRecurringInvoiceStatsForClient = memo2(
|
||||
(String clientId, BuiltMap<String, InvoiceEntity> invoiceMap) =>
|
||||
recurringInvoiceStatsForClient(clientId, invoiceMap));
|
||||
|
||||
EntityStats recurringInvoiceStatsForClient(
|
||||
String clientId, BuiltMap<String, InvoiceEntity> invoiceMap) {
|
||||
int countActive = 0;
|
||||
int countArchived = 0;
|
||||
invoiceMap.forEach((invoiceId, invoice) {
|
||||
if (invoice.clientId == clientId) {
|
||||
if (invoice.isActive) {
|
||||
countActive++;
|
||||
} else if (invoice.isArchived) {
|
||||
countArchived++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return EntityStats(countActive: countActive, countArchived: countArchived);
|
||||
}
|
||||
|
||||
var memoizedRecurringInvoiceStatsForUser = memo2(
|
||||
(String userId, BuiltMap<String, InvoiceEntity> invoiceMap) =>
|
||||
recurringInvoiceStatsForUser(userId, invoiceMap));
|
||||
|
||||
EntityStats recurringInvoiceStatsForUser(
|
||||
String userId, BuiltMap<String, InvoiceEntity> invoiceMap) {
|
||||
int countActive = 0;
|
||||
int countArchived = 0;
|
||||
invoiceMap.forEach((invoiceId, invoice) {
|
||||
if (invoice.assignedUserId == userId) {
|
||||
if (invoice.isActive) {
|
||||
countActive++;
|
||||
} else if (invoice.isDeleted) {
|
||||
countArchived++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return EntityStats(countActive: countActive, countArchived: countArchived);
|
||||
}
|
||||
|
||||
|
||||
bool hasRecurringInvoiceChanges(InvoiceEntity recurringInvoice,
|
||||
BuiltMap<String, InvoiceEntity> recurringInvoiceMap) =>
|
||||
recurringInvoice.isNew
|
||||
? recurringInvoice.isChanged
|
||||
: recurringInvoice != recurringInvoiceMap[recurringInvoice.id];
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
|
|||
import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/task/task_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/FieldGrid.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_list_tile.dart';
|
||||
|
|
@ -176,6 +177,19 @@ class ClientOverview extends StatelessWidget {
|
|||
memoizedInvoiceStatsForClient(client.id, state.invoiceState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if (company.isModuleEnabled(EntityType.recurringInvoice))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
entityType: EntityType.recurringInvoice,
|
||||
title: localization.recurringInvoices,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.recurringInvoice),
|
||||
onLongPress: () => viewModel.onEntityPressed(
|
||||
context, EntityType.recurringInvoice, true),
|
||||
subtitle: memoizedRecurringInvoiceStatsForClient(
|
||||
client.id, state.recurringInvoiceState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if (company.isModuleEnabled(EntityType.payment))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/redux/credit/credit_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/recurring_invoice/recurring_invoice_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_list_tile.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
|
|
@ -44,47 +45,60 @@ class UserView extends StatelessWidget {
|
|||
secondValue: user.phone,
|
||||
),
|
||||
ListDivider(),
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
title: localization.invoices,
|
||||
entityType: EntityType.invoice,
|
||||
onTap: () => viewModel.onEntityPressed(context, EntityType.invoice),
|
||||
onLongPress: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.invoice, true),
|
||||
subtitle:
|
||||
memoizedInvoiceStatsForUser(user.id, state.invoiceState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
userCompany.canViewOrCreate(EntityType.quote)
|
||||
? EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
entityType: EntityType.quote,
|
||||
title: localization.quotes,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.quote),
|
||||
onLongPress: () => viewModel.onEntityPressed(
|
||||
context, EntityType.quote, true),
|
||||
subtitle: memoizedQuoteStatsForUser(
|
||||
user.id,
|
||||
state.quoteState.map,
|
||||
).present(localization.active, localization.archived),
|
||||
)
|
||||
: Container(),
|
||||
userCompany.canViewOrCreate(EntityType.credit)
|
||||
? EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
entityType: EntityType.credit,
|
||||
title: localization.credits,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.credit),
|
||||
onLongPress: () => viewModel.onEntityPressed(
|
||||
context, EntityType.credit, true),
|
||||
subtitle: memoizedCreditStatsForUser(
|
||||
user.id,
|
||||
state.creditState.map,
|
||||
).present(localization.active, localization.archived),
|
||||
)
|
||||
: Container(),
|
||||
if (userCompany.canViewOrCreate(EntityType.invoice))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
title: localization.invoices,
|
||||
entityType: EntityType.invoice,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.invoice),
|
||||
onLongPress: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.invoice, true),
|
||||
subtitle:
|
||||
memoizedInvoiceStatsForUser(user.id, state.invoiceState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if (userCompany.canViewOrCreate(EntityType.recurringInvoice))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
title: localization.recurringInvoices,
|
||||
entityType: EntityType.recurringInvoice,
|
||||
onTap: () => viewModel.onEntityPressed(
|
||||
context, EntityType.recurringInvoice),
|
||||
onLongPress: () => viewModel.onEntityPressed(
|
||||
context, EntityType.recurringInvoice, true),
|
||||
subtitle: memoizedRecurringInvoiceStatsForUser(
|
||||
user.id, state.recurringInvoiceState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if (userCompany.canViewOrCreate(EntityType.quote))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
entityType: EntityType.quote,
|
||||
title: localization.quotes,
|
||||
onTap: () => viewModel.onEntityPressed(context, EntityType.quote),
|
||||
onLongPress: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.quote, true),
|
||||
subtitle: memoizedQuoteStatsForUser(
|
||||
user.id,
|
||||
state.quoteState.map,
|
||||
).present(localization.active, localization.archived),
|
||||
),
|
||||
if (userCompany.canViewOrCreate(EntityType.credit))
|
||||
EntitiesListTile(
|
||||
isFilter: isFilter,
|
||||
entityType: EntityType.credit,
|
||||
title: localization.credits,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.credit),
|
||||
onLongPress: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.credit, true),
|
||||
subtitle: memoizedCreditStatsForUser(
|
||||
user.id,
|
||||
state.creditState.map,
|
||||
).present(localization.active, localization.archived),
|
||||
),
|
||||
|
||||
/*
|
||||
userCompany.canViewOrCreate(EntityType.project)
|
||||
? EntityListTile(
|
||||
|
|
|
|||
Loading…
Reference in New Issue