Added Tax Rate Report
This commit is contained in:
parent
7e0286f615
commit
036fbd7ac8
|
|
@ -566,6 +566,7 @@ abstract class UserSettingsEntity
|
|||
// TODO remove this
|
||||
@nullable
|
||||
@BuiltValueField(wireName: 'accent_color')
|
||||
@nullable
|
||||
String get accentColor;
|
||||
|
||||
@BuiltValueField(wireName: 'table_columns')
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue