Sales Margin & Discounts
Purpose
Sales Margin & Discounts checks commercial quotation lines against minimum margin percentages, minimum margin amounts and maximum discounts. Policies can warn, block confirmation or require approval. Requests, decisions, warnings and authorised overrides leave retained audit evidence.
This guide follows Odoo 19 source with a targeted Odoo 20 comparison. No approval activity, quotation confirmation or runtime test was executed.
Before you start
Install corvus_sale_margin_guard with Sales (sale_management) and Sales Margins (sale_margin) for your exact Odoo major version. No Enterprise-only dependency is declared. Your hosting must permit custom addons.
Confirm product costs, quotation currency and units before using margin thresholds. The calculation uses the line's tax-excluded subtotal and purchase cost multiplied by quantity, converted to company currency at the order date. Margin percentage is margin divided by net revenue; a nonpositive net amount fails an enabled minimum-percentage test.
Access and roles
Sales users read applicable policies and accessible approval evidence and request approval on editable quotations. Margin Policy Administrator maintains policies and includes Margin Approver and Sales Manager permissions. Margin Approver can decide requests when the user belongs to an allowed group for every affected approval policy and has access to the order. Assignment alone does not grant that access.
Margin Override is a distinct role that permits an exception to current violations. Margin Cost Viewer, approvers, policy administrators and Sales Managers can see protected cost and margin fields. Ordinary sales users can see status and threshold guidance without those cost values. Company and native Sales ownership rules still apply; own-document users see own or unassigned approval records unless their Sales role grants broader access.
Setup and menu
Open Sales → Configuration → Margin & Discount Policies. Set company, priority, effective dates and action. Enable at least one threshold and enter its value. Maximum Discount must be between 0 and 100; margin thresholds cannot be negative. A minimum margin amount is measured for the line in company currency.
Optional scopes include Sales Teams, Salespeople, Salesperson Groups, Customers, Customer Tags, Pricelists, Products and Product Categories. Every populated scope must match. One policy wins per line: higher priority first, then specificity and further product/category/customer tie-breakers. Different lines can have different winners.
An Approval policy needs Allowed Approver Groups. Configure self-approval and reason/comment requirements deliberately. Sales → Configuration → Policy Precedence Preview shows candidate ranking for a company, date, salesperson, customer, pricelist and product; Evaluate identifies the winner. It previews policy selection, not a full priced margin calculation.
Sales Settings provides Enable Margin Guard, Show Compliant Status, Schedule Approver Activity, Default Margin Approver and non-commercial product/category exclusions. Guard, compliant display and activity scheduling default to enabled. The default approver is a starting choice, not an exemption from eligibility checks.
Workflow
- Prepare a quotation and review its Margin Guard banner and line status. Correct prices, discounts or costs when the commercial terms are mistaken. The strongest outstanding action across lines controls confirmation: Block outranks Approval, which outranks Warning.
- For Approval Required, choose Request Margin Approval. Enter the business reason and select an eligible assignee. The workflow captures the current quotation and violating lines. When configured, it schedules an activity for that assignee and records the request in chatter.
- The reviewer opens Margin Approvals under the Sales order menu, or the quotation's Margin Approvals smart button. Review the request and snapshots, then choose Approve or Reject and supply the required decision comment. Approval of one's own request is allowed only when every affected policy permits it.
- After approval, confirm the unchanged quotation normally. Pending requests and the newest rejection block confirmation. Material changes to product, quantity, price, discount, costs, taxes, customer, company context or governing policies can make evidence stale; reassess before relying on it.
- For a justified exceptional decision, a user with Margin Override opens Override Margin Policy and supplies the required reason. The override action records evidence and calls quotation confirmation. Treat it as a commercial confirmation action, not merely permission saved for later. A Block policy cannot use the normal approval-request path.
- Review Sales → Reporting → Margin Exceptions or Export Approval History. The export wizard filters by company, request dates and state; Generate CSV produces the download. Warning-only quotations can confirm and create an automatic warning acknowledgement record.
Practice scenario
In an authorised test database, prepare fictional “Harbor Trade Supplies” with a product sold at 100 per unit and purchase cost 70, excluding tax. Configure a product policy with Minimum Margin 25%, Maximum Discount 10% and Action Approval. A 20% discount leaves revenue 80, margin 10 and margin percentage 12.5%; both thresholds are violated. Request approval from an eligible different user, inspect its snapshots and decide whether the exception is justified. These figures and expected states are source-derived; no request or notification was sent.
Troubleshooting and limitations
An approver must satisfy every applicable policy's group restriction, the Margin Approver role and company/order access. A request with unchanged evidence cannot be duplicated while pending. Stale or superseded decisions cannot be reused. A company change is refused while the quotation has evidence in Requested, Approved, Rejected or Overridden state; prepare a new quotation in the target company in that situation.
Sections, notes, nonpositive quantities, down payments, expense lines, native global-discount lines and configured non-commercial products/categories are excluded. This module is a quotation confirmation control; it does not implement a blanket prohibition on every subsequent edit to a confirmed order. Later edits can invalidate evidence and should follow your established order-change process.
Audit records and snapshot lines cannot be directly edited or deleted. Commercial Impact is a calculated measure of policy shortfall/excess discount, not an accounting posting or realised loss. No PDF rendering or notification delivery was tested in this review.
Versions and useful links
Catalogue-qualified versions are Odoo 15, 16, 18, 19 and 20. Odoo 17 source is present but its pair is not catalogue-qualified. The walkthrough is source-reviewed for 19.0; 15–18 workflows remain unreviewed here. The targeted 20.0 comparison keeps the policy/approval flow while adapting unit fingerprint inputs, CSV encoding and access declarations.
Choose your exact version in the Corvus apps catalogue. Related controls include Sales MOQ & Pack Rules and Customer PO Validation. The live catalogue was checked; no demo was launched.
Open the Odoo 19 demo selector for this catalogue-qualified module/version pair. The catalogue listing was verified; no demo was launched.