| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Discuss (mail)
• Purchase (purchase) • Invoicing (account) |
| Lines of code | 2474 |
| Technical Name |
grev_od_purchase_contracts |
| License | OPL-1 |
| Website | https://www.grevlin.com |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Discuss (mail)
• Purchase (purchase) • Invoicing (account) |
| Lines of code | 2474 |
| Technical Name |
grev_od_purchase_contracts |
| License | OPL-1 |
| Website | https://www.grevlin.com |
📄 Purchase ContractsFull Contract Lifecycle Management â Amendments, SLA Tracking, Risk Scoring, Disputes & OWL Dashboard
|
|
|
|
|
|
📞 Need Help?
|
|
Grevlin Procurement Suite Enterprise-Grade Procurement Solutions for Odoo © 2026 Grevlin Global Corp. All Rights Reserved. Compatible with Odoo 19.0 | Licensed under OPL-1 |
Purchase Contracts
The Purchase Contracts module extends Odoo's native purchase agreements (purchase.requisition) into a full Contract Lifecycle Management (CLM) platform. It adds formal amendment governance, milestone and obligation tracking, dispute management, SLA performance history, algorithmic risk scoring, and a real-time OWL KPI dashboard — all anchored to the standard Odoo purchase agreement record.
Overview
This module provides a governed CLM layer on top of purchase.requisition. Rather than maintaining a separate contract model, every feature is applied directly to the native blanket/framework agreement so that existing Odoo purchase flows remain intact.
Key Capabilities
- Amendment Workflow — formal amendment records with before/after diff, multi-level approval routing, and automatic version increment on apply.
- Rule-Based Approval Routing — configurable rules by value threshold, product category, or supplier risk level that auto-populate approval chains.
- Milestone & Payment Schedule — sequenced milestones with computed states (pending / in-progress / completed / overdue) and analytic account support.
- Obligation Register — buyer/supplier contractual duties with monthly, quarterly, or annual recurrence and computed next-due dates.
- Dispute & Claim Management — full dispute lifecycle (open → under review → resolved / escalated → closed) with claimed and settled amount tracking.
- SLA Tracking & Performance History — SLA definitions per contract with monthly auto-snapshots of actuals vs targets.
- Algorithmic Risk Scoring — weighted score (0–100) across five dimensions: SLA performance, compliance status, open disputes, expiry proximity, and supplier risk.
- OWL KPI Dashboard — real-time pipeline banner, KPI cards, activity feed, upcoming milestones, and supplier risk overview.
- SQL Performance Report — grev.contract.performance.report (pivot + graph).
- Expiry Countdown Widget — contract_countdown field widget on the contract form.
- 5 Scheduled Crons — daily expiry alerts, daily auto-renewal, daily milestone/ obligation overdue checks, and monthly SLA auto-snapshots.
Note
Budget commitment and supplier risk integrations are soft dependencies — the module degrades gracefully if those modules are absent.
Configuration
Approval Routing Rules
Routing rules determine which approvers are required for a contract (and its amendments).
- Go to :menuselection:`Purchase --> Contracts --> Configuration --> Routing Rules`.
- Click :guilabel:`Create`.
- Set :guilabel:`Condition Type`:
- Always — rule applies to every contract.
- Value Threshold — applies when contract value falls within :guilabel:`Min Value` and :guilabel:`Max Value`.
- Category — applies when the contract's product category matches :guilabel:`Product Category`.
- Supplier Risk — applies when supplier risk level is medium, high, or critical (read from grev.supplier.intel if installed).
- Set :guilabel:`Approval Type` to Procurement, Legal, or Finance.
- Assign either a specific :guilabel:`Approver` or an :guilabel:`Approver Group` (one of the two is required).
- Set :guilabel:`Sequence` to control evaluation order.
- Click :guilabel:`Save`.
Important
At least one routing rule should cover the always condition to ensure every contract has at least one approver. Rules without a matching approver are skipped silently — verify your rule set by submitting a test contract.
Contract Templates
Templates pre-populate terms and default settings when applied to a contract.
- Go to :menuselection:`Purchase --> Contracts --> Configuration --> Templates`.
- Click :guilabel:`Create`.
- Select :guilabel:`Template Type` (framework / blanket / service / one-time).
- Set :guilabel:`Default Notice Period Days` and :guilabel:`Default Renewal Type`.
- Add default terms in the :guilabel:`Terms` tab.
- Click :guilabel:`Save`.
To apply a template to an open contract, open the contract, select the template in the :guilabel:`Template` field, and click :guilabel:`Apply Template`. Existing contract terms are not removed — template terms are appended.
Scheduled Actions
Five crons ship with the module. All are active by default.
| Cron | Frequency | Purpose |
|---|---|---|
| Contract Expiry Check | Daily | Creates an activity on contracts expiring within their notice_period_days. |
| Contract Auto-Renew | Daily | Renews contracts where auto_renew = True, renewal date is reached, and renewal_count < max_renewals (0 = unlimited). |
| Milestone Overdue Check | Daily | Sets overdue milestones and creates activity alerts on the parent contract. |
| Obligation Overdue Check | Daily | Marks obligations past their due date as overdue and creates activity alerts. |
| SLA Performance Snapshot | Monthly (1st) | Auto-creates grev.purchase.contract.sla.record entries for all active contract SLAs. |
Security Groups
The module defines three groups under grev_purchase_contracts:
Contract User (group_contract_user)
- Read-only access to contracts, amendments, disputes, milestones, obligations, SLA records, and the performance report.
- Cannot create or edit contract records.
Contract Officer (group_contract_officer)
- Create and edit contracts, amendments, milestones, obligations, and disputes.
- Cannot delete records.
- Inherits Contract User permissions.
Contract Manager (group_contract_manager)
- Full CRUD including delete on all contract models.
- Can configure routing rules and templates.
- Can directly activate contracts (bypassing approval when needed).
- Inherits Contract Officer permissions.
Note
Multi-company record rules apply to all models using the pattern ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]. Child records (amendments, disputes, milestones, obligations, SLA records) inherit company_id from the parent contract via a stored related field.
Usage
Creating a Contract
- Navigate to :menuselection:`Purchase --> Contracts --> Contracts`.
- Click :guilabel:`Create`. This opens a new purchase.requisition record.
- Fill in the required fields:
- :guilabel:`Contract Name` — descriptive reference.
- :guilabel:`Vendor` — the supplier partner.
- :guilabel:`Contract Value` — total ceiling value.
- :guilabel:`Validity Start` / :guilabel:`Validity Stop` — contract period.
- :guilabel:`Notice Period Days` — days before expiry to trigger the alert cron.
- Optionally select a :guilabel:`Template` and click :guilabel:`Apply Template` to pre-populate terms.
- Add :guilabel:`Terms`, :guilabel:`SLAs`, and :guilabel:`Penalties` in their tabs.
- Click :guilabel:`Submit for Review` to initiate the approval chain.
Submitting for Approval
Clicking :guilabel:`Submit for Review` calls action_submit_for_review(), which:
- Evaluates all active routing rules against the contract.
- Creates grev.purchase.contract.approval records for each matching rule.
- Moves the contract to state under_review.
Each approver sees their pending approval on the contract's :guilabel:`Approvals` tab. They click :guilabel:`Approve` or :guilabel:`Reject` (with optional comments). When all approval records are approved, the contract moves to active automatically and, if the budget module is installed, commits the budget.
Managing Amendments
- Open an active contract and click the :guilabel:`Amendments` smart button.
- Click :guilabel:`Create`.
- Set :guilabel:`Amendment Type` and fill in :guilabel:`Old Value` and :guilabel:`New Value` to capture the diff.
- Enter a mandatory :guilabel:`Reason`.
- Optionally link :guilabel:`Affected Terms`.
- Click :guilabel:`Submit` to route the amendment through its own approval chain (uses the same routing rules).
- Once all approvals pass, click :guilabel:`Apply`. This records the applied_date, the applied_by user, and increments the parent contract's version field.
Tip
Use the version badge on the contract form header to track how many amendments have been applied. The chatter records every increment automatically.
Tracking SLA Performance
- Open a contract and go to the :guilabel:`SLAs` tab.
- Add SLA lines for each metric (delivery time, quality rate, etc.) with a :guilabel:`Target Value`, :guilabel:`Unit`, and :guilabel:`Measurement Period`.
- Update :guilabel:`Actual Value` on each SLA line as measurements come in. The state field (met / at-risk / breached) recomputes automatically.
- On the first day of each month the cron creates a snapshot grev.purchase.contract.sla.record capturing the current actual vs target. View history via :menuselection:`Purchase --> Contracts --> SLA Records`.
Managing Disputes
- From a contract form, click the :guilabel:`Disputes` smart button.
- Click :guilabel:`Create`, select :guilabel:`Dispute Type`, and enter a :guilabel:`Description` (Html field).
- Optionally link a :guilabel:`Related Purchase Order` and enter :guilabel:`Claimed Amount`.
- Workflow actions on the dispute form:
- :guilabel:`Start Review` → under_review
- :guilabel:`Escalate` → escalated
- :guilabel:`Resolve` → requires :guilabel:`Resolution Type` and :guilabel:`Settled Amount`
- :guilabel:`Close` → closed
Reading the Risk Score
The risk_score (0–100) is computed automatically and stored on the contract. It updates whenever the underlying data changes.
| Dimension | Weight | Source |
|---|---|---|
| SLA Performance | 25% | Ratio of breached/at-risk SLAs to total SLAs. |
| Compliance Status | 20% | compliance_status field (set by compliance module or manually). |
| Open Disputes | 20% | open_dispute_count smart button count. |
| Expiry Proximity | 15% | Days remaining vs notice_period_days. |
| Supplier Risk Level | 20% | supplier_risk_level (read from grev.supplier.intel if installed). |
risk_level bands: Low (0–33) · Medium (34–66) · High (67–100).
Technical Details
Data Model
| Model | Type | Description |
|---|---|---|
| purchase.requisition | Extended | Core contract record; all CLM fields added here. |
| grev.purchase.contract.approval | Model | Per-step approval records for contracts and amendments. |
| grev.purchase.contract.template | Model | Template with default terms and renewal settings. |
| grev.purchase.contract.term | Model + analytic.mixin | Term/clause lines (attached to contract or template). |
| grev.purchase.contract.sla | Model | SLA definition per contract. |
| grev.purchase.contract.penalty | Model | Penalty clause linked to contract/SLA. |
| grev.purchase.contract.routing.rule | Model | Routing rules for auto-populating approval chains. |
| grev.purchase.contract.amendment | Model + mail.thread | Amendment records with sub-approval workflow. |
| grev.purchase.contract.milestone | Model + analytic.mixin | Milestone and payment schedule lines. |
| grev.purchase.contract.obligation | Model | Obligation register with recurrence logic. |
| grev.purchase.contract.dispute | Model + mail.thread | Dispute and claim records. |
| grev.purchase.contract.sla.record | Model | Monthly SLA performance snapshots. |
| grev.contract.performance.report | SQL view | Read-only performance report (pivot + graph). |
OWL Components
Two OWL frontend components are registered:
- contract_dashboard (ir.actions.client)
- Loaded via :menuselection:`Purchase --> Contracts --> Dashboard`. Calls purchase.requisition.get_dashboard_data() to retrieve KPIs, pipeline counts, recent activity, upcoming milestones, and top suppliers by risk.
- contract_countdown (field widget)
- Registered in registry.category("fields"). Displayed on the contract form's expiry date field. Renders a visual countdown in days.
Assets are declared in __manifest__.py under assets.web.assets_backend.
Troubleshooting
Contract Stays in Draft After Submission
Symptom: :guilabel:`Submit for Review` appears to do nothing.
Checks:
- Verify all required fields are filled (vendor, validity dates, contract value).
- Confirm at least one active routing rule exists that matches the contract's value/category/risk profile.
- Check that the routing rule has a valid approver_id or approver_group_id (the _check_approver constraint will warn at save time if both are missing).
Approval Notifications Not Arriving
Symptom: Assigned approvers do not receive email notifications.
Checks:
- Verify the Odoo outgoing mail server is configured and active.
- Confirm approvers have valid email addresses on their res.users record.
- Check that the chatter mail.thread tracking is enabled on the contract (it is by default; do not disable).
Risk Score Not Updating
Symptom: risk_score shows 0 despite breached SLAs or open disputes.
Checks:
- The field is compute + store=True. Trigger a manual write on the contract (e.g., save a note) to force recomputation, or run purchase.requisition._compute_risk_score() directly from a shell.
- If supplier_risk_level shows low unexpectedly, confirm that grev_od_purchase_intel is installed and the supplier has an intel record.
SLA Snapshots Not Created
Symptom: No grev.purchase.contract.sla.record entries appear after the 1st of the month.
Checks:
- Confirm the SLA Performance Snapshot scheduled action is active and its next execution date is set correctly.
- Verify contracts are in active state — the cron skips non-active contracts.
- Check Odoo server logs for cron execution errors.
See Also
External References
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module