This commit is contained in:
Hillel Coren 2020-02-16 12:03:47 +02:00
parent 949f2b4985
commit be449c1fc7
3 changed files with 91 additions and 106 deletions

View File

@ -1,45 +0,0 @@
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:invoiceninja_flutter/redux/reports/reports_state.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
ReportResult invoiceReport({
CompanyEntity company,
ReportsUIState reportsUIState,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, InvoiceEntity> invoiceMap,
}) {
final List<List<ReportElement>> data = [];
final Map<String, double> totalAmounts = {};
final Map<String, double> totalPaid = {};
for (var invoiceId in invoiceMap.keys) {
final invoice = invoiceMap[invoiceId];
final client = clientMap[invoice.clientId];
if (invoice.isDeleted) {
continue;
}
if (!totalAmounts.containsKey(client.id)) {
totalAmounts[client.id] = 0;
totalPaid[client.id] = 0;
}
totalAmounts[client.id] += invoice.amount;
totalPaid[client.id] += invoice.amount - invoice.balance;
}
for (var clientId in clientMap.keys) {
final client = clientMap[clientId];
if (client.isDeleted) {
continue;
}
}
return ReportResult(
columns: [],
data: data,
);
}

View File

@ -137,6 +137,7 @@ class ReportsScreen extends StatelessWidget {
)) ))
.toList(), .toList(),
), ),
if (reportsUIState.group.isNotEmpty)
AppDropdownButton<String>( AppDropdownButton<String>(
labelText: localization.chart, labelText: localization.chart,
value: reportsUIState.chart, value: reportsUIState.chart,
@ -333,7 +334,7 @@ class _ReportDataTableState extends State<ReportDataTable> {
state.uiState.reportsUIState.filters state.uiState.reportsUIState.filters
.rebuild((b) => b..addAll({column: value}))); .rebuild((b) => b..addAll({column: value})));
}), }),
...reportResult.tableRows(context), ...reportResult.tableRows(context, widget.viewModel),
], ],
), ),
), ),
@ -364,9 +365,9 @@ ReportColumnType getReportColumnType(String column) {
class ReportResult { class ReportResult {
ReportResult({ ReportResult({
this.columns, @required this.columns,
this.allColumns, @required this.allColumns,
this.data, @required this.data,
}); });
final List<String> columns; final List<String> columns;
@ -611,7 +612,7 @@ class ReportResult {
]); ]);
} }
List<DataRow> tableRows(BuildContext context) { List<DataRow> tableRows(BuildContext context, ReportsScreenVM viewModel) {
final rows = <DataRow>[]; final rows = <DataRow>[];
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final reportState = store.state.uiState.reportsUIState; final reportState = store.state.uiState.reportsUIState;
@ -629,43 +630,7 @@ class ReportResult {
rows.add(DataRow(cells: cells)); rows.add(DataRow(cells: cells));
} }
} else { } else {
final Map<String, Map<String, double>> totals = {}; viewModel.reportTotals.forEach((group, values) {
for (var i = 0; i < data.length; i++) {
final row = data[i];
for (var j = 0; j < row.length; j++) {
final cell = row[j];
final column = columns[j];
final columnIndex = columns.indexOf(groupBy);
String value = row[columnIndex].renderText(context, column);
if (getReportColumnType(reportState.group) ==
ReportColumnType.dateTime) {
value = convertDateTimeToSqlDate(DateTime.tryParse(value));
if (reportState.subgroup == kReportGroupYear) {
value = value.substring(0, 4) + '-01-01';
} else if (reportState.subgroup == kReportGroupMonth) {
value = value.substring(0, 7) + '-01';
}
}
if (!totals.containsKey(value)) {
totals[value] = {'count': 0};
}
if (column == groupBy) {
totals[value]['count'] += 1;
}
if (cell is ReportNumberValue) {
if (!totals[value].containsKey(column)) {
totals[value][column] = 0;
}
totals[value][column] += cell.value;
}
}
}
totals.forEach((group, values) {
final cells = <DataCell>[]; final cells = <DataCell>[];
for (var column in columns) { for (var column in columns) {
String value = ''; String value = '';
@ -800,7 +765,6 @@ class ReportResult {
rows.add(DataRow(cells: cells)); rows.add(DataRow(cells: cells));
}); });
print('## TOTALS: $totals');
return rows; return rows;
} }
} }

View File

@ -3,15 +3,19 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart'; import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/reports/reports_actions.dart'; import 'package:invoiceninja_flutter/redux/reports/reports_actions.dart';
import 'package:invoiceninja_flutter/redux/reports/reports_state.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/reports/client_report.dart'; import 'package:invoiceninja_flutter/ui/reports/client_report.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart'; import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
import 'package:invoiceninja_flutter/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/dialogs.dart'; import 'package:invoiceninja_flutter/utils/dialogs.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:memoize/memoize.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'reports_screen.dart'; import 'reports_screen.dart';
@ -39,11 +43,13 @@ class ReportsScreenVM {
@required this.onReportColumnsChanged, @required this.onReportColumnsChanged,
@required this.onReportFiltersChanged, @required this.onReportFiltersChanged,
@required this.onReportSorted, @required this.onReportSorted,
@required this.reportTotals,
@required this.reportResult, @required this.reportResult,
}); });
final AppState state; final AppState state;
final ReportResult reportResult; final ReportResult reportResult;
final Map<String, Map<String, double>> reportTotals;
final Function(BuildContext, List<String>) onReportColumnsChanged; final Function(BuildContext, List<String>) onReportColumnsChanged;
final Function(BuildContext, BuiltMap<String, String>) onReportFiltersChanged; final Function(BuildContext, BuiltMap<String, String>) onReportFiltersChanged;
final Function(int, bool) onReportSorted; final Function(int, bool) onReportSorted;
@ -73,9 +79,13 @@ class ReportsScreenVM {
break; break;
} }
print('## TOTALS: ${memoizedReportTotals(reportResult, state.uiState.reportsUIState)}');
return ReportsScreenVM( return ReportsScreenVM(
state: state, state: state,
reportResult: reportResult, reportResult: reportResult,
reportTotals:
memoizedReportTotals(reportResult, state.uiState.reportsUIState),
onReportSorted: (index, ascending) { onReportSorted: (index, ascending) {
store.dispatch(UpdateReportSettings( store.dispatch(UpdateReportSettings(
report: state.uiState.reportsUIState.report, report: state.uiState.reportsUIState.report,
@ -156,3 +166,59 @@ class ReportsScreenVM {
); );
} }
} }
var memoizedReportTotals = memo2((
ReportResult reportResult,
ReportsUIState reportUIState,
) =>
calculateReportTotals(
reportResult: reportResult, reportUIState: reportUIState));
Map<String, Map<String, double>> calculateReportTotals({
ReportResult reportResult,
ReportsUIState reportUIState,
}) {
if (reportUIState.group.isEmpty) {
return null;
}
final Map<String, Map<String, double>> totals = {};
final data = reportResult.data;
final columns = reportResult.columns;
for (var i = 0; i < data.length; i++) {
final row = data[i];
for (var j = 0; j < row.length; j++) {
final cell = row[j];
final column = columns[j];
final columnIndex = columns.indexOf(reportUIState.group);
String group = row[columnIndex].value;
if (getReportColumnType(reportUIState.group) ==
ReportColumnType.dateTime) {
group = convertDateTimeToSqlDate(DateTime.tryParse(group));
if (reportUIState.subgroup == kReportGroupYear) {
group = group.substring(0, 4) + '-01-01';
} else if (reportUIState.subgroup == kReportGroupMonth) {
group = group.substring(0, 7) + '-01';
}
}
if (!totals.containsKey(group)) {
totals[group] = {'count': 0};
}
if (column == reportUIState.group) {
totals[group]['count'] += 1;
}
if (cell is ReportNumberValue) {
if (!totals[group].containsKey(column)) {
totals[group][column] = 0;
}
totals[group][column] += cell.value;
}
}
}
return totals;
}