Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 16 additions & 31 deletions addons/account/models/account_tax.py
Original file line number Diff line number Diff line change
Expand Up @@ -2211,31 +2211,22 @@ def tax_group_grouping_function(base_line, tax_data):
})

# Subtotals.
def subtotal_grouping_function(base_line, tax_data):
return tax_data['tax'].tax_group_id.preceding_subtotal or untaxed_amount_subtotal_label
if not subtotals:
subtotals[untaxed_amount_subtotal_label]

base_lines_aggregated_values = self._aggregate_base_lines_tax_details(base_lines, subtotal_grouping_function)
values_per_grouping_key = self._aggregate_base_lines_aggregated_values(base_lines_aggregated_values)
for preceding_subtotal, values in values_per_grouping_key.items():
preceding_subtotal = preceding_subtotal or untaxed_amount_subtotal_label
subtotal = subtotals[preceding_subtotal]
is_first_preceding_subtotal = (
preceding_subtotal == untaxed_amount_subtotal_label
or (
untaxed_amount_subtotal_label not in subtotals_order
and subtotals_order[preceding_subtotal] == 0
)
)
if is_first_preceding_subtotal:
# The first subtotal is always the base of the whole document.
subtotal['base_amount_currency'] += values['total_excluded_currency']
subtotal['base_amount'] += values['total_excluded']
else:
# Otherwise, it's the base of the first tax in the group.
subtotal['base_amount_currency'] += values['base_amount_currency']
subtotal['base_amount'] += values['base_amount']
subtotal['tax_amount_currency'] += values['tax_amount_currency']
subtotal['tax_amount'] += values['tax_amount']
ordered_subtotals = sorted(subtotals.items(), key=lambda item: subtotals_order.get(item[0], 0))
accumulated_tax_amount_currency = 0.0
accumulated_tax_amount = 0.0
for subtotal_label, subtotal in ordered_subtotals:
subtotal['name'] = subtotal_label
subtotal['base_amount_currency'] = tax_totals_summary['base_amount_currency'] + accumulated_tax_amount_currency
subtotal['base_amount'] = tax_totals_summary['base_amount'] + accumulated_tax_amount
for tax_group in subtotal['tax_groups']:
subtotal['tax_amount_currency'] += tax_group['tax_amount_currency']
subtotal['tax_amount'] += tax_group['tax_amount']
accumulated_tax_amount_currency += tax_group['tax_amount_currency']
accumulated_tax_amount += tax_group['tax_amount']
tax_totals_summary['subtotals'].append(subtotal)

# Cash rounding
cash_rounding_lines = [base_line for base_line in base_lines if base_line['special_type'] == 'cash_rounding']
Expand Down Expand Up @@ -2272,7 +2263,7 @@ def subtotal_grouping_function(base_line, tax_data):
max_subtotal, max_tax_group = max(
[
(subtotal, tax_group)
for subtotal in subtotals.values()
for subtotal in tax_totals_summary['subtotals']
for tax_group in subtotal['tax_groups']
],
key=lambda item: item[1]['tax_amount_currency'],
Expand All @@ -2284,12 +2275,6 @@ def subtotal_grouping_function(base_line, tax_data):
tax_totals_summary['tax_amount_currency'] += cash_rounding_base_amount_currency
tax_totals_summary['tax_amount'] += cash_rounding_base_amount

# Flat the subtotals.
ordered_subtotals = sorted(subtotals.items(), key=lambda item: subtotals_order.get(item[0], 0))
for subtotal_label, subtotal in ordered_subtotals:
subtotal['name'] = subtotal_label
tax_totals_summary['subtotals'].append(subtotal)

# Subtract the cash rounding from the untaxed amounts.
cash_rounding_base_amount_currency = tax_totals_summary.get('cash_rounding_base_amount_currency', 0.0)
cash_rounding_base_amount = tax_totals_summary.get('cash_rounding_base_amount', 0.0)
Expand Down
64 changes: 24 additions & 40 deletions addons/account/static/src/helpers/account_tax.js
Original file line number Diff line number Diff line change
Expand Up @@ -971,39 +971,31 @@ export const accountTaxHelpers = {
}

// Subtotals.
const subtotal_grouping_function = (base_line, tax_data) =>
tax_data.tax.tax_group_id.preceding_subtotal || untaxed_amount_subtotal_label;

base_lines_aggregated_values = this.aggregate_base_lines_tax_details(base_lines, subtotal_grouping_function);
values_per_grouping_key = this.aggregate_base_lines_aggregated_values(base_lines_aggregated_values);
if (!Object.keys(subtotals).length) {
subtotals[untaxed_amount_subtotal_label] = {
tax_groups: [],
tax_amount_currency: 0.0,
tax_amount: 0.0,
base_amount_currency: 0.0,
base_amount: 0.0,
};
}

for (const values of Object.values(values_per_grouping_key)) {
const preceding_subtotal = values.grouping_key || untaxed_amount_subtotal_label;
if (!(preceding_subtotal in subtotals)) {
subtotals[preceding_subtotal] = {
tax_groups: [],
tax_amount_currency: 0.0,
tax_amount: 0.0,
base_amount_currency: 0.0,
base_amount: 0.0,
};
}
const is_first_preceding_subtotal =
preceding_subtotal === untaxed_amount_subtotal_label ||
(!(untaxed_amount_subtotal_label in subtotals_order) &&
subtotals_order[preceding_subtotal] === 0);
const subtotal = subtotals[preceding_subtotal];
if (is_first_preceding_subtotal) {
// The first subtotal is always the base of the whole document.
subtotal.base_amount_currency += values.total_excluded_currency;
subtotal.base_amount += values.total_excluded;
} else {
// Otherwise, it's the base of the first tax in the group.
subtotal.base_amount_currency += values.base_amount_currency;
subtotal.base_amount += values.base_amount;
const ordered_subtotals = Array.from(Object.entries(subtotals))
.sort((a, b) => (subtotals_order[a[0]] || 0) - (subtotals_order[b[0]] || 0));
let accumulated_tax_amount_currency = 0.0;
let accumulated_tax_amount = 0.0;
for (const [subtotal_label, subtotal] of ordered_subtotals) {
subtotal.name = subtotal_label;
subtotal.base_amount_currency = tax_totals_summary.base_amount_currency + accumulated_tax_amount_currency;
subtotal.base_amount = tax_totals_summary.base_amount + accumulated_tax_amount;
for (const tax_group of subtotal.tax_groups) {
subtotal.tax_amount_currency += tax_group.tax_amount_currency;
subtotal.tax_amount += tax_group.tax_amount;
accumulated_tax_amount_currency += tax_group.tax_amount_currency;
accumulated_tax_amount += tax_group.tax_amount;
}
subtotal.tax_amount_currency += values.tax_amount_currency;
subtotal.tax_amount += values.tax_amount;
tax_totals_summary.subtotals.push(subtotal);
}

// Cash rounding
Expand Down Expand Up @@ -1035,7 +1027,7 @@ export const accountTaxHelpers = {
subtotals[untaxed_amount_subtotal_label].base_amount_currency += cash_rounding_base_amount_currency;
subtotals[untaxed_amount_subtotal_label].base_amount += cash_rounding_base_amount;
} else if (strategy === 'biggest_tax') {
const [max_subtotal, max_tax_group] = Array.from(Object.values(subtotals))
const [max_subtotal, max_tax_group] = tax_totals_summary.subtotals
.flatMap(subtotal => subtotal.tax_groups.map(tax_group => [subtotal, tax_group]))
.reduce((a, b) => (b[1].tax_amount_currency > a[1].tax_amount_currency ? b : a));

Expand All @@ -1049,14 +1041,6 @@ export const accountTaxHelpers = {
}
}

// Flat the subtotals.
const ordered_subtotals = Array.from(Object.entries(subtotals))
.sort((a, b) => (subtotals_order[a[0]] || 0) - (subtotals_order[b[0]] || 0));
ordered_subtotals.forEach(([subtotal_label, subtotal]) => {
subtotal.name = subtotal_label;
tax_totals_summary.subtotals.push(subtotal);
});

// Subtract the cash rounding from the untaxed amounts.
const cash_rounding_base_amount_currency = tax_totals_summary.cash_rounding_base_amount_currency || 0.0;
const cash_rounding_base_amount = tax_totals_summary.cash_rounding_base_amount || 0.0;
Expand Down
14 changes: 7 additions & 7 deletions addons/account/tests/test_taxes_tax_totals_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -1969,7 +1969,7 @@ def _test_preceding_subtotal(self):
'subtotals': [
{
'name': "Untaxed Amount",
'base_amount_currency': 1300.0,
'base_amount_currency': 3300.0,
'tax_amount_currency': 126.0,
'tax_groups': [
{
Expand All @@ -1982,7 +1982,7 @@ def _test_preceding_subtotal(self):
},
{
'name': "PRE GROUP 1",
'base_amount_currency': 1200.0,
'base_amount_currency': 3426.0,
'tax_amount_currency': 120.0,
'tax_groups': [
{
Expand All @@ -1995,7 +1995,7 @@ def _test_preceding_subtotal(self):
},
{
'name': "PRE GROUP 2",
'base_amount_currency': 1200.0,
'base_amount_currency': 3546.0,
'tax_amount_currency': 300.0,
'tax_groups': [
{
Expand Down Expand Up @@ -2033,7 +2033,7 @@ def _test_preceding_subtotal(self):
'subtotals': [
{
'name': "Untaxed Amount",
'base_amount_currency': 1200.0,
'base_amount_currency': 1500.0,
'tax_amount_currency': 360.0,
'tax_groups': [
{
Expand All @@ -2046,7 +2046,7 @@ def _test_preceding_subtotal(self):
},
{
'name': "PRE GROUP 1",
'base_amount_currency': 500.0,
'base_amount_currency': 1860.0,
'tax_amount_currency': 82.0,
'tax_groups': [
{
Expand All @@ -2065,7 +2065,7 @@ def _test_preceding_subtotal(self):
},
{
'name': "PRE GROUP 2",
'base_amount_currency': 300.0,
'base_amount_currency': 1942.0,
'tax_amount_currency': -75.0,
'tax_groups': [
{
Expand Down Expand Up @@ -2124,7 +2124,7 @@ def _test_preceding_subtotal_with_tax_group(self):
},
{
'name': "Tax withholding",
'base_amount_currency': 100.0,
'base_amount_currency': 110.0,
'tax_amount_currency': -47.0,
'tax_groups': [
{
Expand Down