import 'package:flutter/foundation.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/static/static_state.dart'; import 'package:memoize/memoize.dart'; import 'package:built_collection/built_collection.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; InvoiceItemEntity convertExpenseToInvoiceItem({ @required ExpenseEntity expense, @required BuiltMap categoryMap, @required CompanyEntity company, }) { return InvoiceItemEntity().rebuild((b) => b ..typeId = InvoiceItemEntity.TYPE_EXPENSE ..expenseId = expense.id ..productKey = categoryMap[expense.categoryId]?.name ?? '' ..notes = expense.publicNotes ..quantity = company.defaultQuantity || !company.enableProductQuantity ? 1 : null ..cost = company.settings.enableInclusiveTaxes ? expense.convertedAmount : expense.convertedNetAmount ..taxName1 = company.numberOfItemTaxRates >= 1 ? expense.taxName1 : '' ..taxRate1 = company.numberOfItemTaxRates >= 1 ? expense.calculatetaxRate1 : 0 ..taxName2 = company.numberOfItemTaxRates >= 2 ? expense.taxName2 : '' ..taxRate2 = company.numberOfItemTaxRates >= 2 ? expense.calculatetaxRate2 : 0 ..taxName3 = company.numberOfItemTaxRates >= 3 ? expense.taxName3 : '' ..taxRate3 = company.numberOfItemTaxRates >= 3 ? expense.calculatetaxRate3 : 0); } var memoizedDropdownExpenseList = memo9( (BuiltMap expenseMap, BuiltList expenseList, BuiltMap clientMap, BuiltMap userMap, BuiltMap vendorMap, BuiltMap invoiceMap, BuiltMap expenseCategoryMap, StaticState staticState, String clientId) => dropdownExpensesSelector(expenseMap, expenseList, clientMap, userMap, vendorMap, invoiceMap, expenseCategoryMap, staticState, clientId)); List dropdownExpensesSelector( BuiltMap expenseMap, BuiltList expenseList, BuiltMap clientMap, BuiltMap userMap, BuiltMap vendorMap, BuiltMap invoiceMap, BuiltMap expenseCategoryMap, StaticState staticState, String clientId) { final list = expenseList.where((expenseId) { final expense = expenseMap[expenseId]; /* if (clientId != null && clientId > 0 && expense.clientId != clientId) { return false; } */ return expense.isActive; }).toList(); list.sort((expenseAId, expenseBId) { final expenseA = expenseMap[expenseAId]; final expenseB = expenseMap[expenseBId]; return expenseA.compareTo( expenseB, ExpenseFields.expenseDate, true, clientMap, userMap, vendorMap, invoiceMap, expenseCategoryMap, staticState); }); return list; } var memoizedFilteredExpenseList = memo9((SelectionState selectionState, BuiltMap expenseMap, BuiltMap clientMap, BuiltMap vendorMap, BuiltMap userMap, ListUIState expenseListState, BuiltMap invoiceMap, BuiltMap expenseCategoryMap, StaticState staticState) => filteredExpensesSelector( selectionState, expenseMap, clientMap, vendorMap, userMap, expenseListState, invoiceMap, expenseCategoryMap, staticState)); List filteredExpensesSelector( SelectionState selectionState, BuiltMap expenseMap, BuiltMap clientMap, BuiltMap vendorMap, BuiltMap userMap, ListUIState expenseListState, BuiltMap invoiceMap, BuiltMap expenseCategoryMap, StaticState staticState) { final filterEntityId = selectionState.filterEntityId; final filterEntityType = selectionState.filterEntityType; final list = expenseMap.keys.where((expenseId) { final expense = expenseMap[expenseId]; final vendor = vendorMap[expense.vendorId] ?? VendorEntity(id: expense.vendorId); final client = clientMap[expense.clientId] ?? ClientEntity(id: expense.clientId); if (expense.id == selectionState.selectedId) { return true; } if (filterEntityType != null) { if (filterEntityType == EntityType.client && expense.clientId != filterEntityId) { return false; } else if (filterEntityType == EntityType.vendor && expense.vendorId != filterEntityId) { return false; } else if (filterEntityType == EntityType.expenseCategory && expense.categoryId != filterEntityId) { return false; } else if (filterEntityType == EntityType.user && expense.assignedUserId != filterEntityId) { return false; } else if (filterEntityType == EntityType.project && expense.projectId != filterEntityId) { return false; } else if (filterEntityType == EntityType.invoice && expense.invoiceId != filterEntityId) { return false; } } else if (expense.vendorId != null && !vendor.isActive) { return false; } else if (expense.clientId != null && !client.isActive) { return false; } if (!expense.matchesStates(expenseListState.stateFilters)) { return false; } if (!expense.matchesStatuses(expenseListState.statusFilters)) { return false; } if (expenseListState.custom1Filters.isNotEmpty && !expenseListState.custom1Filters.contains(expense.customValue1)) { return false; } if (expenseListState.custom2Filters.isNotEmpty && !expenseListState.custom2Filters.contains(expense.customValue2)) { return false; } return expense.matchesFilter(expenseListState.filter); }).toList(); list.sort((expenseAId, expenseBId) { final expenseA = expenseMap[expenseAId]; final expenseB = expenseMap[expenseBId]; return expenseA.compareTo( expenseB, expenseListState.sortField, expenseListState.sortAscending, clientMap, userMap, vendorMap, invoiceMap, expenseCategoryMap, staticState); }); return list; } var memoizedExpenseStatsForVendor = memo2( (String vendorId, BuiltMap expenseMap) => expenseStatsForVendor(vendorId, expenseMap)); EntityStats expenseStatsForVendor( String vendorId, BuiltMap expenseMap) { int countActive = 0; int countArchived = 0; expenseMap.forEach((expenseId, expense) { if (expense.vendorId == vendorId) { if (expense.isActive) { countActive++; } else if (expense.isArchived) { countArchived++; } } }); return EntityStats(countActive: countActive, countArchived: countArchived); } var memoizedExpenseStatsForClient = memo2( (String clientId, BuiltMap expenseMap) => expenseStatsForClient(clientId, expenseMap)); EntityStats expenseStatsForClient( String clientId, BuiltMap expenseMap) { int countActive = 0; int countArchived = 0; expenseMap.forEach((expenseId, expense) { if (expense.clientId == clientId) { if (expense.isActive) { countActive++; } else if (expense.isArchived) { countArchived++; } } }); return EntityStats(countActive: countActive, countArchived: countArchived); } var memoizedClientExpenseList = memo2( (BuiltMap expenseMap, String clientId) => clientExpenseList(expenseMap, clientId)); List clientExpenseList( BuiltMap expenseMap, String clientId) { final list = expenseMap.keys.where((expenseid) { final expense = expenseMap[expenseid]; if (clientId != null && clientId != null && expense.clientId != clientId) { return false; } return expense.isActive && !expense.isInvoiced; }).toList(); list.sort((idA, idB) => expenseMap[idA] .listDisplayName .compareTo(expenseMap[idB].listDisplayName)); return list; } var memoizedExpenseStatsForProject = memo2(( String projectId, BuiltMap expenseMap, ) => expenseStatsForProject(projectId, expenseMap)); EntityStats expenseStatsForProject( String projectId, BuiltMap expenseMap) { int countActive = 0; int countArchived = 0; expenseMap.forEach((expenseId, expense) { if (expense.projectId == projectId) { if (expense.isActive) { countActive++; } else if (expense.isArchived) { countArchived++; } } }); return EntityStats(countActive: countActive, countArchived: countArchived); } var memoizedExpenseStatsForUser = memo2(( String userId, BuiltMap expenseMap, ) => expenseStatsForUser(userId, expenseMap)); EntityStats expenseStatsForUser( String userId, BuiltMap expenseMap) { int countActive = 0; int countArchived = 0; expenseMap.forEach((expenseId, expense) { if (expense.assignedUserId == userId) { if (expense.isActive) { countActive++; } else if (expense.isArchived) { countArchived++; } } }); return EntityStats(countActive: countActive, countArchived: countArchived); } bool hasExpenseChanges( ExpenseEntity expense, BuiltMap expenseMap) => expense.isNew ? expense.isChanged : expense != expenseMap[expense.id];