Skip to content

[FIX] account_invoice_triple_discount: allow discounts over 100% - #2416

Open
dcatarino wants to merge 1 commit into
OCA:18.0from
dcatarino:18.0-account_invoice_triple_discount-fix-discount-limit
Open

dcatarino wants to merge 1 commit into
OCA:18.0from
dcatarino:18.0-account_invoice_triple_discount-fix-discount-limit

Conversation

@dcatarino

@dcatarino dcatarino commented Jul 27, 2026

Copy link
Copy Markdown

Problem

triple.discount.mixin redefines the core discount field of account.move.line, and write() redirects any write of discount into discount1. Core discount has no upper bound (account/models/account_move_line.py#L371-L375), so CHECK (discountN <= 100.0) rejects values that Odoo itself produces and stores.

account_edi_ubl_cii infers the discount percentage from the imported amounts, uncapped:

and it does so with rounding deliberately disabled, so the raw value is stored as-is: _disable_discount_precision forces the Discount precision to 13 digits (account/models/decimal_precision.py#L6-L13).

A vendor credit note whose price_subtotal has the opposite sign of quantity * price_unit therefore yields exactly 200%:

quantity = -2, price_unit = 15.47, discount = 200.00000000000017, price_subtotal = 30.94

Installing this module on a database that already holds such a line aborts the whole upgrade, because post_init_hook copies discount into discount1 after the constraints have been created:

new row for relation "account_move_line" violates check constraint
"account_move_line_discount1_limit"

The constraints cannot prevent the situation either — they are created while discount1 is still NULL, so they always apply successfully and only fail later, on data that was already valid under core Odoo.

Reproduce

  1. On a database with account_edi_ubl_cii installed, import a Peppol vendor bill or credit note whose line amounts imply a discount above 100% (or simply UPDATE account_move_line SET discount = 200 WHERE id = <any line>).
  2. Install account_invoice_triple_discount.
  3. The install aborts with the constraint violation above.

Fix

Remove the three CHECK (discountN <= 100.0) constraints.

This is safe:

  • The computation already handles values above 100%: discount1 = 200 gives a factor of -1 and an aggregated discount of 200.
  • The bound was one-sided — negative discounts (surcharges) remain allowed and are exercised by test_01_discounts, which sets discount1 = -5.
  • The message "must be lower than 100%" did not match the SQL, which allowed exactly 100.

No migration script is needed: the constraints are reflected as ir.model.constraint xml_ids, so ir.model.data._process_end() drops them on upgrade.

Added test_08_discount_over_100 as a regression test.

Note

19.0 carries the identical constraints (ported to models.Constraint) and needs the same fix. Happy to open the forward-port once this is agreed.

This mixin replaces the core `discount` field of `account.move.line`,
which has no upper bound, and `write()` redirects any write of
`discount` into `discount1`. `CHECK (discountN <= 100.0)` therefore
rejects values that core Odoo itself produces: `account_edi_ubl_cii`
infers the discount percentage from the imported amounts, uncapped and
with rounding disabled, so a credit note whose `price_subtotal` has the
opposite sign of `quantity * price_unit` yields exactly 200%.

Installing this module on a database holding such a line aborts, since
`post_init_hook` copies `discount` into `discount1` after the
constraints have been created.

Removing the constraints is safe: the computation already handles values
over 100%, as `discount1 = 200` gives a factor of -1 and an aggregated
discount of 200. The bound was one-sided anyway, since negative
discounts stay allowed and are covered by `test_01_discounts`.
@OCA-git-bot OCA-git-bot added series:18.0 mod:account_invoice_triple_discount Module account_invoice_triple_discount labels Jul 27, 2026

@StefanRijnhart StefanRijnhart left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe replace them with ORM constraints? This will allow us to keep the feature, as well as an easy override option if not desired. Such a change would also be compatible with the installation on existing databases that have one or more existing lines with a discount > 100.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:account_invoice_triple_discount Module account_invoice_triple_discount series:18.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants