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,24 +137,25 @@ class ReportsScreen extends StatelessWidget {
))
.toList(),
),
AppDropdownButton<String>(
labelText: localization.chart,
value: reportsUIState.chart,
blankValue: '',
showBlank: true,
onChanged: (dynamic value) {
viewModel.onSettingsChanged(chart: value);
},
items: reportResult.columns
.where((column) =>
getReportColumnType(column) ==
ReportColumnType.number)
.map((column) => DropdownMenuItem(
child: Text(localization.lookup(column)),
value: column,
))
.toList(),
),
if (reportsUIState.group.isNotEmpty)
AppDropdownButton<String>(
labelText: localization.chart,
value: reportsUIState.chart,
blankValue: '',
showBlank: true,
onChanged: (dynamic value) {
viewModel.onSettingsChanged(chart: value);
},
items: reportResult.columns
.where((column) =>
getReportColumnType(column) ==
ReportColumnType.number)
.map((column) => DropdownMenuItem(
child: Text(localization.lookup(column)),
value: column,
))
.toList(),
),
if (hasCustomDate) ...[
DatePicker(
labelText: localization.startDate,
@ -333,7 +334,7 @@ class _ReportDataTableState extends State<ReportDataTable> {
state.uiState.reportsUIState.filters
.rebuild((b) => b..addAll({column: value})));
}),
...reportResult.tableRows(context),
...reportResult.tableRows(context, widget.viewModel),
],
),
),
@ -364,9 +365,9 @@ ReportColumnType getReportColumnType(String column) {
class ReportResult {
ReportResult({
this.columns,
this.allColumns,
this.data,
@required this.columns,
@required this.allColumns,
@required this.data,
});
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 store = StoreProvider.of<AppState>(context);
final reportState = store.state.uiState.reportsUIState;
@ -629,43 +630,7 @@ class ReportResult {
rows.add(DataRow(cells: cells));
}
} else {
final Map<String, Map<String, double>> totals = {};
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) {
viewModel.reportTotals.forEach((group, values) {
final cells = <DataCell>[];
for (var column in columns) {
String value = '';
@ -800,7 +765,6 @@ class ReportResult {
rows.add(DataRow(cells: cells));
});
print('## TOTALS: $totals');
return rows;
}
}

View File

@ -3,15 +3,19 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.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/redux/app/app_state.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/ui/reports/client_report.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/dialogs.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:memoize/memoize.dart';
import 'package:redux/redux.dart';
import 'reports_screen.dart';
@ -39,11 +43,13 @@ class ReportsScreenVM {
@required this.onReportColumnsChanged,
@required this.onReportFiltersChanged,
@required this.onReportSorted,
@required this.reportTotals,
@required this.reportResult,
});
final AppState state;
final ReportResult reportResult;
final Map<String, Map<String, double>> reportTotals;
final Function(BuildContext, List<String>) onReportColumnsChanged;
final Function(BuildContext, BuiltMap<String, String>) onReportFiltersChanged;
final Function(int, bool) onReportSorted;
@ -73,9 +79,13 @@ class ReportsScreenVM {
break;
}
print('## TOTALS: ${memoizedReportTotals(reportResult, state.uiState.reportsUIState)}');
return ReportsScreenVM(
state: state,
reportResult: reportResult,
reportTotals:
memoizedReportTotals(reportResult, state.uiState.reportsUIState),
onReportSorted: (index, ascending) {
store.dispatch(UpdateReportSettings(
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;
}