Added Aging Report

This commit is contained in:
Gianfranco Gasbarri 2020-03-12 23:26:58 +00:00
parent d2799cf379
commit f1c7affbe2
4 changed files with 181 additions and 2 deletions

View File

@ -0,0 +1,162 @@
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/utils/enums.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/tax_rate_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/reports/reports_state.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:memoize/memoize.dart';
enum AgingReportFields {
age,
client,
invoice,
invoice_amount,
invoice_balance,
date,
due_date,
currency
}
var memoizedAgingReport = memo7((
UserCompanyEntity userCompany,
ReportsUIState reportsUIState,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, UserEntity> userMap,
StaticState staticState,
) =>
agingReport(userCompany, reportsUIState, invoiceMap, clientMap, paymentMap,
userMap, staticState));
ReportResult agingReport(
UserCompanyEntity userCompany,
ReportsUIState reportsUIState,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, UserEntity> userMap,
StaticState staticState,
) {
final List<List<ReportElement>> data = [];
BuiltList<AgingReportFields> columns;
final reportSettings = userCompany.settings.reportSettings;
final agingReportSettings =
reportSettings != null && reportSettings.containsKey(kReportAging)
? reportSettings[kReportAging]
: ReportSettingsEntity();
final defaultColumns = [
AgingReportFields.invoice,
AgingReportFields.age,
AgingReportFields.invoice_amount,
AgingReportFields.due_date,
AgingReportFields.client,
];
if (agingReportSettings.columns.isNotEmpty) {
columns = BuiltList(agingReportSettings.columns
.map((e) => EnumUtils.fromString(AgingReportFields.values, e))
.toList());
} else {
columns = BuiltList(defaultColumns);
}
for (var invoiceId in invoiceMap.keys) {
final invoice = invoiceMap[invoiceId];
final client = clientMap[invoice.clientId];
int ageInDays = 0;
if (invoice.isPastDue && invoice.balance > 0) {
final now = DateTime.now();
final dueDate = DateTime.tryParse(
invoice.partialDueDate == null || invoice.partialDueDate.isEmpty
? invoice.dueDate
: invoice.partialDueDate);
if (dueDate != null) {
ageInDays = now.difference(dueDate).inDays;
}
}
bool skip = false;
final List<ReportElement> row = [];
for (var column in columns) {
dynamic value = '';
switch (column) {
case AgingReportFields.client:
value = client.displayName;
break;
case AgingReportFields.invoice:
value = invoice.listDisplayName;
break;
case AgingReportFields.invoice_amount:
value = invoice.amount;
break;
case AgingReportFields.currency:
value = staticState.currencyMap[client.currencyId]?.name ??
staticState.currencyMap[client.settings.currencyId]?.name;
break;
case AgingReportFields.age:
value = ageInDays.toDouble();
break;
case AgingReportFields.invoice_balance:
value = invoice.balance;
break;
case AgingReportFields.date:
value = invoice.date;
break;
case AgingReportFields.due_date:
value = invoice.dueDate;
break;
}
if (!ReportResult.matchField(
value: value,
userCompany: userCompany,
reportsUIState: reportsUIState,
column: EnumUtils.parse(column),
)) {
skip = true;
}
if (value.runtimeType == bool) {
row.add(invoice.getReportBool(value: value));
} else if (column == AgingReportFields.age) {
row.add(invoice.getReportNumber(
value: value,
currencyId: client.settings.currencyId,
formatNumberType: FormatNumberType.int));
} else if (value.runtimeType == double || value.runtimeType == int) {
row.add(invoice.getReportNumber(
value: value, currencyId: client.settings.currencyId));
} else {
row.add(invoice.getReportString(value: value));
}
}
if (!skip) {
data.add(row);
}
}
final selectedColumns = columns.map((item) => EnumUtils.parse(item)).toList();
data.sort((rowA, rowB) =>
sortReportTableRows(rowA, rowB, agingReportSettings, selectedColumns));
return ReportResult(
allColumns:
AgingReportFields.values.map((e) => EnumUtils.parse(e)).toList(),
columns: columns.map((item) => EnumUtils.parse(item)).toList(),
defaultColumns:
defaultColumns.map((item) => EnumUtils.parse(item)).toList(),
data: data,
);
}

View File

@ -150,7 +150,7 @@ class ReportsScreen extends StatelessWidget {
onChanged: (dynamic value) =>
viewModel.onSettingsChanged(report: value),
items: [
//kReportAging,
kReportAging,
kReportClient,
kReportCredit,
//kReportDocument,
@ -479,9 +479,11 @@ ReportColumnType getReportColumnType(String column, BuildContext context) {
'cost',
'total',
'invoice_amount',
'invoice_balance',
'tax_rate',
'tax_amount',
'tax_paid',
'age',
'payment_amount'
].contains(column)) {
return ReportColumnType.number;

View File

@ -12,6 +12,7 @@ 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/aging_report.dart';
import 'package:invoiceninja_flutter/ui/reports/client_report.dart';
import 'package:invoiceninja_flutter/ui/reports/document_report.dart';
import 'package:invoiceninja_flutter/ui/reports/expense_report.dart';
@ -196,6 +197,17 @@ class ReportsScreenVM {
state.staticState,
);
break;
case kReportAging:
reportResult = memoizedAgingReport(
state.userCompany,
state.uiState.reportsUIState,
state.invoiceState.map,
state.clientState.map,
state.paymentState.map,
state.userState.map,
state.staticState,
);
break;
default:
reportResult = memoizedClientReport(
state.userCompany,

View File

@ -1085,7 +1085,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
'tax_name': 'Tax Name',
'tax_amount': 'Tax Amount',
'tax_paid': 'Tax Paid Amount',
'payment_amount': 'Payment Amount'
'payment_amount': 'Payment Amount',
'age': 'Age'
},
'sq': {
'company1': 'Custom Company 1',
@ -33036,6 +33037,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
String get paymentAmount => _localizedValues[localeCode]['payment_amount'];
String get age => _localizedValues[localeCode]['age'];
String lookup(String key) {
final lookupKey = toSnakeCase(key);
return _localizedValues[localeCode][lookupKey] ??