Added Tax Rate Report

This commit is contained in:
Gianfranco Gasbarri 2020-03-02 23:44:54 +00:00
parent 7e0286f615
commit 036fbd7ac8
5 changed files with 218 additions and 35 deletions

View File

@ -566,6 +566,7 @@ abstract class UserSettingsEntity
// TODO remove this
@nullable
@BuiltValueField(wireName: 'accent_color')
@nullable
String get accentColor;
@BuiltValueField(wireName: 'table_columns')

View File

@ -18,10 +18,6 @@ enum QuoteReportFields {
client_address2,
client_shipping_address1,
client_shipping_address2,
//vendor,
//vendor_city,
//vendor_state,
//vendor_country,
status,
discount,
po_number,
@ -83,7 +79,6 @@ ReportResult quoteReport(
QuoteReportFields.balance,
QuoteReportFields.due_date,
QuoteReportFields.client,
//QuoteReportFields.vendor,
];
if (quoteReportSettings.columns.isNotEmpty) {
@ -134,18 +129,6 @@ ReportResult quoteReport(
case QuoteReportFields.client_shipping_address2:
value = client.shippingAddress2;
break;
//case QuoteReportFields.vendor:
// value = vendor.listDisplayName;
// break;
//case QuoteReportFields.vendor_city:
// value = vendor.city;
// break;
//case QuoteReportFields.vendor_state:
// value = vendor.state;
// break;
//case QuoteReportFields.vendor_country:
// value = staticState.countryMap[vendor.countryId].listDisplayName;
// break;
case QuoteReportFields.status:
value = staticState.invoiceStatusMap[quote.statusId].name;
break;
@ -244,13 +227,14 @@ ReportResult quoteReport(
}
}
data.sort(
(rowA, rowB) => sortReportTableRows(rowA, rowB, quoteReportSettings));
final selectedColumns = columns.map((item) => EnumUtils.parse(item)).toList();
data.sort((rowA, rowB) =>
sortReportTableRows(rowA, rowB, quoteReportSettings, selectedColumns));
return ReportResult(
allColumns:
QuoteReportFields.values.map((e) => EnumUtils.parse(e)).toList(),
columns: columns.map((item) => EnumUtils.parse(item)).toList(),
columns: selectedColumns,
defaultColumns:
defaultColumns.map((item) => EnumUtils.parse(item)).toList(),
data: data,

View File

@ -160,7 +160,7 @@ class ReportsScreen extends StatelessWidget {
//kReportProduct,
//kReportProfitAndLoss,
//kReportTask,
//kReportTaxRate,
kReportTaxRate,
kReportQuote,
]
.map((report) =>
@ -401,19 +401,22 @@ class _ReportDataTableState extends State<ReportDataTable> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
DataTable(
sortColumnIndex: reportSettings.sortTotalsIndex != null &&
reportResult.columns.length >
reportSettings.sortTotalsIndex
? reportSettings.sortTotalsIndex
: null,
sortAscending: reportSettings.sortTotalsAscending ?? true,
columns: reportResult.totalColumns(
context,
(index, ascending) =>
widget.viewModel
.onReportTotalsSorted(index, ascending)),
rows: reportResult.totalRows(context),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
sortColumnIndex: reportSettings.sortTotalsIndex != null &&
reportResult.columns.length >
reportSettings.sortTotalsIndex
? reportSettings.sortTotalsIndex
: null,
sortAscending: reportSettings.sortTotalsAscending ?? true,
columns: reportResult.totalColumns(
context,
(index, ascending) =>
widget.viewModel
.onReportTotalsSorted(index, ascending)),
rows: reportResult.totalRows(context),
),
),
],
),
@ -472,9 +475,14 @@ ReportColumnType getReportColumnType(String column, BuildContext context) {
'paid_to_date',
'amount',
'quantity',
'pridce',
'price',
'cost',
'total',
'invoice_amount',
'tax_rate',
'tax_amount',
'tax_paid',
'payment_amount'
].contains(column)) {
return ReportColumnType.number;
} else if (['is_active'].contains(column)) {

View File

@ -21,6 +21,7 @@ import 'package:invoiceninja_flutter/ui/reports/product_report.dart';
import 'package:invoiceninja_flutter/ui/reports/quote_report.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
import 'package:invoiceninja_flutter/ui/reports/task_report.dart';
import 'package:invoiceninja_flutter/ui/reports/tax_rate_report.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
@ -171,6 +172,18 @@ class ReportsScreenVM {
state.staticState,
);
break;
case kReportTaxRate:
reportResult = memoizedTaxRateReport(
state.userCompany,
state.uiState.reportsUIState,
state.taxRateState.map,
state.invoiceState.map,
state.clientState.map,
state.paymentState.map,
state.userState.map,
state.staticState,
);
break;
// TODO: Obtain credit map
//case kReportCredit:
// reportResult = memoizedCreditReport(

View File

@ -0,0 +1,177 @@
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:memoize/memoize.dart';
enum TaxRateReportFields {
client,
invoice,
invoice_amount,
tax_name,
tax_rate,
tax_amount,
tax_paid,
payment_amount,
currency
}
var memoizedTaxRateReport = memo8((
UserCompanyEntity userCompany,
ReportsUIState reportsUIState,
BuiltMap<String, TaxRateEntity> taxRateMap,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, UserEntity> userMap,
StaticState staticState,
) =>
taxRateReport(userCompany, reportsUIState, taxRateMap, invoiceMap,
clientMap, paymentMap, userMap, staticState));
ReportResult taxRateReport(
UserCompanyEntity userCompany,
ReportsUIState reportsUIState,
BuiltMap<String, TaxRateEntity> taxRateMap,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
BuiltMap<String, UserEntity> userMap,
StaticState staticState,
) {
final List<List<ReportElement>> data = [];
BuiltList<TaxRateReportFields> columns;
final reportSettings = userCompany.settings.reportSettings;
final taxRateReportSettings =
reportSettings != null && reportSettings.containsKey(kReportTaxRate)
? reportSettings[kReportTaxRate]
: ReportSettingsEntity();
final defaultColumns = [
TaxRateReportFields.tax_name,
TaxRateReportFields.tax_amount,
TaxRateReportFields.tax_paid,
TaxRateReportFields.invoice_amount,
TaxRateReportFields.invoice,
];
if (taxRateReportSettings.columns.isNotEmpty) {
columns = BuiltList(taxRateReportSettings.columns
.map((e) => EnumUtils.fromString(TaxRateReportFields.values, e))
.toList());
} else {
columns = BuiltList(defaultColumns);
}
for (var invoiceId in invoiceMap.keys) {
final invoice = invoiceMap[invoiceId];
final client = clientMap[invoice.clientId];
final invoiceTaxAmount = invoice.calculateTaxes(invoice.usesInclusiveTaxes);
final invoicePaidAmount = invoice.amount - invoice.balance;
for (var i in Iterable<int>.generate(3)) {
bool skip = false;
final List<ReportElement> row = [];
final taxName = [invoice.taxName1, invoice.taxName2, invoice.taxName3][i];
final taxRate = [invoice.taxRate1, invoice.taxRate2, invoice.taxRate3][i];
if (taxRate == null) {
continue;
}
final invoiceCurrentTaxAmount = invoiceTaxAmount[taxName];
if (invoiceCurrentTaxAmount == null || invoiceCurrentTaxAmount == 0)
continue;
double invoiceCurrentTaxPaidAmount;
if (invoice.amount != null &&
invoice.amount > 0 &&
invoiceCurrentTaxAmount != null &&
invoiceCurrentTaxAmount > 0) {
invoiceCurrentTaxPaidAmount =
invoicePaidAmount / invoice.amount * invoiceCurrentTaxAmount;
} else {
invoiceCurrentTaxPaidAmount = 0;
}
for (var column in columns) {
dynamic value = '';
switch (column) {
case TaxRateReportFields.client:
value = client.displayName;
break;
case TaxRateReportFields.invoice:
value = invoice.listDisplayName;
break;
case TaxRateReportFields.invoice_amount:
value = invoice.amount;
break;
case TaxRateReportFields.tax_name:
value = taxName;
break;
case TaxRateReportFields.tax_rate:
value = taxRate;
break;
case TaxRateReportFields.tax_amount:
value = invoiceCurrentTaxAmount ?? 0;
break;
case TaxRateReportFields.tax_paid:
value = invoiceCurrentTaxPaidAmount;
break;
case TaxRateReportFields.payment_amount:
value = invoicePaidAmount;
break;
case TaxRateReportFields.currency:
value = staticState.currencyMap[client.currencyId]?.name ??
staticState.currencyMap[client.settings.currencyId]?.name;
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 (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, taxRateReportSettings, selectedColumns));
return ReportResult(
allColumns:
TaxRateReportFields.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,
);
}