Include Due Date, Taxable, and Tax Rate columns in Invoice Item Report #273
This commit is contained in:
parent
92204b13e2
commit
2b2f6b701a
|
|
@ -1210,30 +1210,42 @@ abstract class InvoiceItemEntity
|
|||
@nullable
|
||||
int get createdAt;
|
||||
|
||||
/*
|
||||
double taxAmount(bool useInclusiveTaxes, int precision) {
|
||||
double taxAmount(InvoiceEntity invoice, int precision) {
|
||||
double calculateTaxAmount(double rate) {
|
||||
double taxAmount;
|
||||
if (rate == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (useInclusiveTaxes) {
|
||||
taxAmount = total - (total / (1 + (rate / 100)));
|
||||
final lineTotal = total(invoice);
|
||||
if (invoice.usesInclusiveTaxes) {
|
||||
taxAmount = lineTotal - (lineTotal / (1 + (rate / 100)));
|
||||
} else {
|
||||
taxAmount = total * rate / 100;
|
||||
taxAmount = lineTotal * rate / 100;
|
||||
}
|
||||
return round(taxAmount, precision);
|
||||
}
|
||||
|
||||
return calculateTaxAmount(taxRate1) + calculateTaxAmount(taxRate2) +
|
||||
return calculateTaxAmount(taxRate1) +
|
||||
calculateTaxAmount(taxRate2) +
|
||||
calculateTaxAmount(taxRate3);
|
||||
}
|
||||
|
||||
double netTotal(bool useInclusiveTaxes, int precision) =>
|
||||
total - taxAmount(useInclusiveTaxes, precision);
|
||||
*/
|
||||
double netTotal(InvoiceEntity invoice, int precision) =>
|
||||
total(invoice) - taxAmount(invoice, precision);
|
||||
|
||||
double get total => round(quantity * cost, 2);
|
||||
double total(InvoiceEntity invoice) {
|
||||
var total = quantity * cost;
|
||||
|
||||
if (discount != 0) {
|
||||
if (invoice.isAmountDiscount) {
|
||||
total = total - discount;
|
||||
} else {
|
||||
total = total - (discount / 100 * total);
|
||||
}
|
||||
}
|
||||
|
||||
return round(total, 2);
|
||||
}
|
||||
|
||||
bool get isTask => typeId == TYPE_TASK;
|
||||
|
||||
|
|
@ -1245,9 +1257,31 @@ abstract class InvoiceItemEntity
|
|||
cost == 0 &&
|
||||
quantity == 0 &&
|
||||
customValue1.isEmpty &&
|
||||
customValue2.isEmpty;
|
||||
customValue2.isEmpty &&
|
||||
customValue3.isEmpty &&
|
||||
customValue4.isEmpty;
|
||||
|
||||
// TODO add custom 3 and 4
|
||||
bool get hasTaxes =>
|
||||
taxRate1 != 0 ||
|
||||
taxRate2 != 0 ||
|
||||
taxRate3 != 0 ||
|
||||
taxName1.isNotEmpty ||
|
||||
taxName2.isNotEmpty ||
|
||||
taxName3.isNotEmpty;
|
||||
|
||||
String get taxRates {
|
||||
final parts = <String>[];
|
||||
if (taxName1.isNotEmpty) {
|
||||
parts.add(taxName1);
|
||||
}
|
||||
if (taxName2.isNotEmpty) {
|
||||
parts.add(taxName2);
|
||||
}
|
||||
if (taxName3.isNotEmpty) {
|
||||
parts.add(taxName3);
|
||||
}
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
InvoiceItemEntity applyTax(TaxRateEntity taxRate,
|
||||
{bool isSecond = false, bool isThird = false}) {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class InvoiceItemListTile extends StatelessWidget {
|
|||
title: Row(
|
||||
children: <Widget>[
|
||||
Expanded(child: Text(invoiceItem.productKey)),
|
||||
Text(formatNumber(invoiceItem.total, context,
|
||||
Text(formatNumber(invoiceItem.total(invoice), context,
|
||||
clientId: invoice.clientId)),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ class EntityPresenter {
|
|||
'calculated_rate',
|
||||
'duration',
|
||||
'net_amount',
|
||||
'net_total',
|
||||
].contains(field);
|
||||
|
||||
return value;
|
||||
|
|
|
|||
|
|
@ -576,7 +576,7 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
readOnly: true,
|
||||
enabled: false,
|
||||
initialValue: formatNumber(
|
||||
lineItems[index].total, context,
|
||||
lineItems[index].total(invoice), context,
|
||||
clientId: invoice.clientId),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ enum InvoiceItemReportFields {
|
|||
cost,
|
||||
quantity,
|
||||
profit,
|
||||
lineTotal,
|
||||
total,
|
||||
discount,
|
||||
custom1,
|
||||
custom2,
|
||||
|
|
@ -26,6 +26,11 @@ enum InvoiceItemReportFields {
|
|||
invoiceNumber,
|
||||
invoiceDate,
|
||||
client,
|
||||
dueDate,
|
||||
hasTaxes,
|
||||
taxRates,
|
||||
taxAmount,
|
||||
netTotal,
|
||||
}
|
||||
|
||||
var memoizedInvoiceItemReport = memo6((
|
||||
|
|
@ -81,6 +86,7 @@ ReportResult lineItemReport(
|
|||
for (var entry in invoiceMap.entries) {
|
||||
final invoice = entry.value;
|
||||
final client = clientMap[invoice.clientId];
|
||||
final precision = staticState.currencyMap[client.currencyId].precision;
|
||||
|
||||
if (invoice.isDeleted || client.isDeleted) {
|
||||
continue;
|
||||
|
|
@ -105,9 +111,8 @@ ReportResult lineItemReport(
|
|||
value = productId == null ? 0.0 : productMap[productId].cost;
|
||||
break;
|
||||
case InvoiceItemReportFields.profit:
|
||||
value = productId == null
|
||||
? 0.0
|
||||
: lineItem.total - productMap[productId].cost;
|
||||
value = lineItem.netTotal(invoice, precision) -
|
||||
(productId == null ? 0.0 : productMap[productId].cost);
|
||||
break;
|
||||
case InvoiceItemReportFields.custom1:
|
||||
value = lineItem.customValue1;
|
||||
|
|
@ -124,7 +129,7 @@ ReportResult lineItemReport(
|
|||
case InvoiceItemReportFields.notes:
|
||||
value = lineItem.notes;
|
||||
break;
|
||||
case InvoiceItemReportFields.lineTotal:
|
||||
case InvoiceItemReportFields.total:
|
||||
value = lineItem.total;
|
||||
break;
|
||||
case InvoiceItemReportFields.productKey:
|
||||
|
|
@ -142,6 +147,21 @@ ReportResult lineItemReport(
|
|||
case InvoiceItemReportFields.client:
|
||||
value = client.displayName;
|
||||
break;
|
||||
case InvoiceItemReportFields.dueDate:
|
||||
value = invoice.dueDate;
|
||||
break;
|
||||
case InvoiceItemReportFields.hasTaxes:
|
||||
value = lineItem.hasTaxes;
|
||||
break;
|
||||
case InvoiceItemReportFields.taxRates:
|
||||
value = lineItem.taxRates;
|
||||
break;
|
||||
case InvoiceItemReportFields.taxAmount:
|
||||
value = lineItem.taxAmount(invoice, precision);
|
||||
break;
|
||||
case InvoiceItemReportFields.netTotal:
|
||||
value = lineItem.netTotal(invoice, precision);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ReportResult.matchField(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ enum QuoteItemReportFields {
|
|||
cost,
|
||||
quantity,
|
||||
profit,
|
||||
lineTotal,
|
||||
total,
|
||||
discount,
|
||||
custom1,
|
||||
custom2,
|
||||
|
|
@ -26,6 +26,11 @@ enum QuoteItemReportFields {
|
|||
quoteNumber,
|
||||
quoteDate,
|
||||
client,
|
||||
validUntil,
|
||||
hasTaxes,
|
||||
taxRates,
|
||||
taxAmount,
|
||||
netTotal,
|
||||
}
|
||||
|
||||
var memoizedQuoteItemReport = memo6((
|
||||
|
|
@ -81,6 +86,7 @@ ReportResult lineItemReport(
|
|||
for (var entry in invoiceMap.entries) {
|
||||
final invoice = entry.value;
|
||||
final client = clientMap[invoice.clientId];
|
||||
final precision = staticState.currencyMap[client.currencyId].precision;
|
||||
|
||||
if (invoice.isDeleted || client.isDeleted) {
|
||||
continue;
|
||||
|
|
@ -105,9 +111,8 @@ ReportResult lineItemReport(
|
|||
value = productId == null ? 0.0 : productMap[productId].cost;
|
||||
break;
|
||||
case QuoteItemReportFields.profit:
|
||||
value = productId == null
|
||||
? 0.0
|
||||
: lineItem.total - productMap[productId].cost;
|
||||
value = lineItem.netTotal(invoice, precision) -
|
||||
(productId == null ? 0.0 : productMap[productId].cost);
|
||||
break;
|
||||
case QuoteItemReportFields.custom1:
|
||||
value = lineItem.customValue1;
|
||||
|
|
@ -124,7 +129,7 @@ ReportResult lineItemReport(
|
|||
case QuoteItemReportFields.notes:
|
||||
value = lineItem.notes;
|
||||
break;
|
||||
case QuoteItemReportFields.lineTotal:
|
||||
case QuoteItemReportFields.total:
|
||||
value = lineItem.total;
|
||||
break;
|
||||
case QuoteItemReportFields.productKey:
|
||||
|
|
@ -142,6 +147,21 @@ ReportResult lineItemReport(
|
|||
case QuoteItemReportFields.client:
|
||||
value = client.displayName;
|
||||
break;
|
||||
case QuoteItemReportFields.validUntil:
|
||||
value = invoice.dueDate;
|
||||
break;
|
||||
case QuoteItemReportFields.hasTaxes:
|
||||
value = lineItem.hasTaxes;
|
||||
break;
|
||||
case QuoteItemReportFields.taxRates:
|
||||
value = lineItem.taxRates;
|
||||
break;
|
||||
case QuoteItemReportFields.taxAmount:
|
||||
value = lineItem.taxAmount(invoice, precision);
|
||||
break;
|
||||
case QuoteItemReportFields.netTotal:
|
||||
value = lineItem.netTotal(invoice, precision);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ReportResult.matchField(
|
||||
|
|
|
|||
|
|
@ -534,6 +534,8 @@ enum ReportColumnType {
|
|||
}
|
||||
|
||||
ReportColumnType getReportColumnType(String column, BuildContext context) {
|
||||
column = toSnakeCase(column);
|
||||
|
||||
ReportColumnType convertCustomFieldType(String type) {
|
||||
if (type == kFieldTypeDate) {
|
||||
return ReportColumnType.date;
|
||||
|
|
@ -1125,6 +1127,9 @@ class ReportResult {
|
|||
final sortedColumns = columns.toList()
|
||||
..sort((String str1, String str2) => str1.compareTo(str2));
|
||||
|
||||
for (String column in sortedColumns)
|
||||
print('## $column => ${getReportColumnType(column, context)}');
|
||||
|
||||
final totalColumns = [
|
||||
DataColumn(
|
||||
label: Text(localization.currency),
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
static final Map<String, Map<String, String>> _localizedValues = {
|
||||
'en': {
|
||||
// STARTER: lang key - do not remove comment
|
||||
'net_total': 'Net Total',
|
||||
'has_taxes': 'Has Taxes',
|
||||
'import_customers': 'Import Customers',
|
||||
'imported_customers': 'Successfully started importing customers',
|
||||
'login_success': 'Successful Login',
|
||||
|
|
@ -60405,6 +60407,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
_localizedValues[localeCode]['imported_customers'] ??
|
||||
_localizedValues['en']['imported_customers'];
|
||||
|
||||
String get hasTaxes =>
|
||||
_localizedValues[localeCode]['has_taxes'] ??
|
||||
_localizedValues['en']['has_taxes'];
|
||||
|
||||
String get netTotal =>
|
||||
_localizedValues[localeCode]['net_total'] ??
|
||||
_localizedValues['en']['net_total'];
|
||||
|
||||
String lookup(String key) {
|
||||
final lookupKey = toSnakeCase(key);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue