Skip to content

[FIX] sale: Recompute global discount on order line updates #855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: 18.0
Choose a base branch
from

Conversation

rvar-odoo
Copy link

  • Fixed issue where global discount lines were not updating when products were
    added, updated, or removed from a sale order.
  • Automatically removes global discount when no regular order lines remain.
  • Groups discount lines by tax combinations to ensure correct tax calculations.
  • Ensures discount line appears at the end of order lines using sequence=999.
  • Hooks into sale.order.line create/write/unlink to trigger discount updates.

This ensures accurate global discount behavior and maintains tax compliance.

@robodoo
Copy link

robodoo commented Jul 23, 2025

Pull request status dashboard

@rvar-odoo rvar-odoo force-pushed the 18.0-global_discount_sale-rvar branch 3 times, most recently from db41525 to f3138a5 Compare July 23, 2025 05:42
Copy link

@ramh-odoo ramh-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current commit message doesn't clearly explain the purpose of the changes properly. Please update the commit message. It should ideally include:

The motivation behind this PR
The behavior before this PR
The desired behavior after this PR

This helps reviewers quickly understand the context and impact of the changes.

Comment on lines 35 to 48
for line in lines:
if (
line.product_id
and line.order_id
and line.order_id.company_id.sale_discount_product_id
):
if (
line.product_id.id
!= line.order_id.company_id.sale_discount_product_id.id
):
if (
line.order_id.has_global_discount
and line.order_id.global_discount_percentage
):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we combine all these conditions into a single if statement?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sir, actually i have done this to be easier to add print/logging at each level. will update it .

Comment on lines 18 to 19
else:
return super(SaleOrderDiscount, company_self).action_apply_discount()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we return early and remove the unnecessary else block for better readability?

@rvar-odoo rvar-odoo force-pushed the 18.0-global_discount_sale-rvar branch from f3138a5 to 50f01a4 Compare July 23, 2025 08:59
Copy link

@maad-odoo maad-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments

"summary": "Manage global discounts in sale orders efficiently.",
"category": "Tutorials/Sale Discount Management",
"depends": ["sale_management"],
"data": [],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this if not required

Comment on lines 8 to 10
has_global_discount = fields.Boolean(
string="Has Global Discount", compute="_compute_has_global_discount", store=True
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
has_global_discount = fields.Boolean(
string="Has Global Discount", compute="_compute_has_global_discount", store=True
)
has_global_discount = fields.Boolean(string="Has Global Discount", compute="_compute_has_global_discount", store=True)

Comment on lines 13 to 15
@api.depends(
"order_line", "order_line.product_id", "company_id.sale_discount_product_id"
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@api.depends(
"order_line", "order_line.product_id", "company_id.sale_discount_product_id"
)
@api.depends( "order_line", "order_line.product_id", "company_id.sale_discount_product_id")


def write(self, vals):
result = super().write(vals)
# If order lines were modified, update discount

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

Comment on lines 72 to 79

regular_lines = self._get_regular_lines()
discount_lines = self._get_discount_lines()

if not regular_lines:
if discount_lines:
discount_lines.unlink()
self.global_discount_percentage = 0
return

if discount_lines:
discount_lines.unlink()

self._create_global_discount_lines(self.global_discount_percentage / 100)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why there are unnecessary lines left in between ??

return False

lines = self.env["sale.order.line"].create(vals_list)
return lines

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments are unnecessary and there are unnecessary lines left inbetween

@api.model_create_multi
def create(self, vals_list):
lines = super().create(vals_list)
# Avoid triggering for discount product lines to prevent infinite loop

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

def unlink(self):
orders = self.mapped("order_id")
result = super().unlink()
# After unlinking, update discount on affected orders

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

Comment on lines 45 to 46

# Update discounts for affected orders

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Motivation :
Global discounts in sale orders were not behaving as expected in multi-company
 and multi-tax setups. Reviewers reported that discount lines were not updated
 or removed when order lines changed, leading to incorrect totals and
 tax inconsistencies.

Behavior Before:
- Adding/removing/updating sale order lines did not update the global discount.
- Global discount lines remained even when no regular order lines existed.
- Discount lines were not grouped by tax combinations, causing tax mismatches.
- Discount lines could appear in the middle of the order lines.

Behavior After:
- Global discount lines now update automatically when sale order lines are
created, modified, or deleted.
- Global discount is removed when no regular order lines remain.
- Discount amounts are grouped by tax combinations for correct tax application.
- Discount lines are positioned at the end of the order lines.
- Sale order line hooks (`create`, `write`, `unlink`) trigger global discount
 recalculation.

This improves accuracy of global discount behavior, ensures tax compliance,
and aligns with expected user workflows.
@rvar-odoo rvar-odoo force-pushed the 18.0-global_discount_sale-rvar branch from 50f01a4 to acae4b4 Compare July 28, 2025 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants