### Configure and Use Global Discounts (Example - Python) Source: https://context7.com/oca/sale-workflow/llms.txt Provides example Python code demonstrating how to create, assign, and apply global discounts within the Odoo sale workflow. It shows the creation of a discount record, assignment to a partner, and how discounts are reflected in a sale order. ```Python # Create a global discount global_discount = self.env['global.discount'].create({ 'name': 'VIP Customer 10%', 'discount': 10.0, 'discount_scope': 'sale', 'account_id': discount_account.id, 'company_id': company.id, }) # Assign to a partner partner.write({ 'customer_global_discount_ids': [(4, global_discount.id)] }) # Create sale order - discount auto-applied from partner sale_order = self.env['sale.order'].create({ 'partner_id': partner.id, }) # Or manually add discounts to an order sale_order.write({ 'global_discount_ids': [(6, 0, [discount1.id, discount2.id])] }) # Check discount amounts print(f"Untaxed before discount: {sale_order.amount_untaxed_before_global_discounts}") print(f"Global discount amount: {sale_order.amount_global_discount}") print(f"Final untaxed: {sale_order.amount_untaxed}") print(f"Final total: {sale_order.amount_total}") ``` -------------------------------- ### GET /oca/sale-workflow/product-prices Source: https://github.com/oca/sale-workflow/blob/18.0/pricelist_cache_rest/readme/DESCRIPTION.md Retrieves product prices from the pricelist cache. Authorization is handled via auth_api_key. ```APIDOC ## GET /oca/sale-workflow/product-prices ### Description Provides an endpoint to expose product prices cached by pricelist_cache. ### Method GET ### Endpoint /oca/sale-workflow/product-prices ### Parameters #### Query Parameters - **auth_api_key** (string) - Required - API key for authorization. ### Request Example ``` GET /oca/sale-workflow/product-prices?auth_api_key=YOUR_API_KEY ``` ### Response #### Success Response (200) - **product_id** (string) - The unique identifier for the product. - **price** (number) - The current price of the product. - **currency** (string) - The currency of the price. #### Response Example ```json { "products": [ { "product_id": "prod_123", "price": 19.99, "currency": "USD" }, { "product_id": "prod_456", "price": 25.50, "currency": "EUR" } ] } ``` ``` -------------------------------- ### Example: Using Product Recommendations - Python Source: https://context7.com/oca/sale-workflow/llms.txt This Python code snippet demonstrates how to use the Product Recommendation Wizard. It shows how to create a wizard instance, set recommendation parameters, generate recommendations, review them, and finally apply them to a sale order. ```python # Open recommendation wizard from sale order sale_order = self.env['sale.order'].browse(order_id) wizard = self.env['sale.order.recommendation'].create({ 'order_id': sale_order.id, 'months': 12, # Look back 12 months 'line_amount': 20, # Get top 20 recommendations 'recommendations_order': 'units_delivered desc', 'sale_recommendation_price_origin': 'last_sale_price', }) # Generate recommendations wizard.generate_recommendations() # Review and modify recommendation lines for line in wizard.line_ids: print(f"Product: {line.product_name}") print(f"Times delivered: {line.times_delivered}") print(f"Units delivered: {line.units_delivered}") print(f"Price: {line.price_unit}") # Set quantity to add line.units_included = 10 # Apply recommendations to sale order wizard.action_accept() ``` -------------------------------- ### Programmatically Create and Use Product Sets in Odoo Source: https://context7.com/oca/sale-workflow/llms.txt This example demonstrates how to programmatically create a product set, add lines to it, and then use the `SaleProductSetWizard` to add this set to a sale order. It shows the typical workflow for managing product sets via Odoo's ORM. ```python # Create a product set product_set = self.env['product.set'].create({ 'name': 'Office Starter Kit', 'partner_id': False, # Available to all customers }) # Add lines to the set self.env['product.set.line'].create([ { 'product_set_id': product_set.id, 'product_id': desk_product.id, 'quantity': 1, 'sequence': 10, }, { 'product_set_id': product_set.id, 'product_id': chair_product.id, 'quantity': 1, 'sequence': 20, }, ]) # Add set to a sale order via wizard wizard = self.env['sale.product.set.wizard'].create({ 'order_id': sale_order.id, 'product_set_id': product_set.id, 'quantity': 2, # Multiplier for set quantities 'skip_existing_products': True, }) wizard.add_set() ``` -------------------------------- ### Add Filter Domain for Sale Order Product Recommendations Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_recommendation/readme/CONFIGURE.md This snippet shows how to add a filter domain to include or exclude specific recommended products. An example is provided to filter out 'service' product types. ```python 1. Go to *Sales > Configuration > Settings > Sale order recommendations*. 2. Add a filter in section *Sale order product recommendation domain* Example: `[("product_type", "!=", "service")]` ``` -------------------------------- ### Create Sale Order Types via XML (XML) Source: https://context7.com/oca/sale-workflow/llms.txt XML examples for creating predefined sale order types in Odoo. These examples illustrate how to set names, sequences, warehouses, and other default parameters for different sale order scenarios. ```xml Standard Sale direct 30 Wholesale one 15 ``` -------------------------------- ### Example cURL Request for Pricelist API (Shell) Source: https://context7.com/oca/sale-workflow/llms.txt Demonstrates how to call the pricelist REST API using cURL. It specifies the HTTP method, URL, and required headers for API key authentication and content type. ```shell # Using curl with API key authentication curl -X GET \ "https://your-odoo-instance.com/pricelist/42" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" ``` -------------------------------- ### GET /pricelist/{partner_id} Source: https://github.com/oca/sale-workflow/blob/18.0/pricelist_cache_rest/static/description/index.html Retrieves cached product prices for a given partner ID. The response format can be customized via ir.exports configuration. ```APIDOC ## GET /pricelist/{partner_id} ### Description Retrieves cached product prices for a given partner ID. The response format can be customized via ir.exports configuration. ### Method GET ### Endpoint /pricelist/$partner_id ### Parameters #### Path Parameters - **partner_id** (integer) - Required - The ID of the partner for whom to retrieve prices. #### Query Parameters None #### Request Body None ### Request Example ```bash curl -X GET "http://your.odoo/pricelist/$partner_id" -H "accept: /" -H "API-KEY: XYZ" ``` ### Response #### Success Response (200) - **products** (array) - A list of dictionaries, each containing product information. - **id** (integer) - The product ID. - **price** (float) - The cached price for the product. #### Response Example ```json [ {"id": $product_id, "price": $price}, {"id": $product_id, "price": $price}, {"id": $product_id, "price": $price} ] ``` ### Error Handling - **401 Unauthorized**: If the API-KEY is missing or invalid. - **404 Not Found**: If the partner_id does not exist. ``` -------------------------------- ### Retrieve Pricelist Cache Data via GET Request Source: https://github.com/oca/sale-workflow/blob/18.0/pricelist_cache_rest/README.rst This snippet demonstrates how to retrieve cached product prices for a specific partner ID using a GET request. It requires the partner ID in the URL and an 'API-KEY' header for authorization. The default response is a list of dictionaries containing product IDs and their prices. ```bash curl -X GET "http://your.odoo/pricelist/$partner_id" -H "accept: /" -H "API-KEY: XYZ" ``` -------------------------------- ### Configure Sale Order Product Recommendation to Force Zero Units Included Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_recommendation/readme/CONFIGURE.md This snippet describes how to force the inclusion of all recommended products in the sale order, allowing for subsequent quantity edits. This is achieved by selecting 'Force zero units included'. ```text 1. Go to *Sales > Configuration > Settings > Sale order recommendations*. 2. Select *Force zero units included* ``` -------------------------------- ### Recompute Sale Order Line Attributes (Python) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_line_product_attribute_values/readme/CONFIGURE.md This Python code snippet demonstrates how to manually recompute product template attribute value IDs for sale order lines. It targets lines with associated attribute line IDs and utilizes the `_compute_all_product_template_attribute_value_ids` method. This is intended to be used in a scheduled action after module installation. ```python env["sale.order.line"].search([ ("product_template_id.attribute_line_ids", "!=", []), ])._compute_all_product_template_attribute_value_ids() ``` -------------------------------- ### Topic Title Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Sets the font weight for topic titles to bold, making them visually distinct. ```CSS p.topic-title { font-weight: bold ``` -------------------------------- ### GET /pricelist/ Source: https://context7.com/oca/sale-workflow/llms.txt Retrieves all cached prices for a given partner's pricelist. Requires API key authentication. ```APIDOC ## GET /pricelist/ ### Description Retrieves all cached prices for the given partner's pricelist. This endpoint is protected by API key authentication. ### Method GET ### Endpoint /pricelist/ #### Path Parameters - **partner** (integer) - Required - The ID of the partner for whom to retrieve the pricelist. #### Query Parameters None #### Request Body None ### Request Example ```bash curl -X GET \ "https://your-odoo-instance.com/pricelist/42" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" ``` ### Response #### Success Response (200) - **product_id** (integer) - The ID of the product. - **pricelist_id** (integer) - The ID of the pricelist. - **price** (float) - The cached price for the product on the pricelist. #### Response Example ```json [ { "product_id": 101, "pricelist_id": 1, "price": 99.99 }, { "product_id": 102, "pricelist_id": 1, "price": 149.50 } ] ``` #### Error Response (401 Unauthorized) - **message** (string) - Indicates missing or invalid API key. ``` -------------------------------- ### Simple List Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Applies standard margin-bottom to simple ordered and unordered lists to ensure spacing between them and subsequent content. ```CSS ol.simple, ul.simple { margin-bottom: 1em } ``` -------------------------------- ### GET /pricelist/{partner_id} Source: https://github.com/oca/sale-workflow/blob/18.0/pricelist_cache_rest/README.rst Retrieves cached product prices for a given partner ID. Authorization is required via an API-KEY. ```APIDOC ## GET /pricelist/{partner_id} ### Description Retrieves cached product prices for a specific customer (partner). This endpoint is secured using an API key. ### Method GET ### Endpoint `/pricelist/$partner_id` ### Parameters #### Path Parameters - **partner_id** (integer) - Required - The ID of the partner for whom to retrieve prices. #### Query Parameters None #### Request Body None ### Request Example ```bash curl -X GET "http://your.odoo/pricelist/123" -H "accept: /" -H "API-KEY: XYZ" ``` ### Response #### Success Response (200) - **products** (array) - A list of dictionaries, where each dictionary contains the product ID and its cached price. - **id** (integer) - The product ID. - **price** (float) - The cached price of the product. #### Response Example ```json [ {"id": 1, "price": 100.50}, {"id": 2, "price": 75.00}, {"id": 3, "price": 200.75} ] ``` ### Error Handling - **401 Unauthorized**: If the API-KEY is missing or invalid. - **404 Not Found**: If the partner ID does not exist. ``` -------------------------------- ### Topic Section Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Sets the margin for topic sections, providing consistent spacing around them. ```CSS div.topic { margin: 2em } ``` -------------------------------- ### Credits and Label Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Styles for 'credits' (often smaller, italicized text) and 'label' (ensuring whitespace is preserved, useful for fixed-width text). ```CSS p.credits { font-style: italic ; font-size: smaller } p.label { white-space: nowrap } ``` -------------------------------- ### GET /oca/sale-workflow/pricelist/{partner_id} Source: https://github.com/oca/sale-workflow/blob/18.0/pricelist_cache_rest/readme/USAGE.md Retrieves customer prices for a given partner ID. The response schema can be customized via 'Pricelist Cache Parser' ir.exports configuration. ```APIDOC ## GET /oca/sale-workflow/pricelist/{partner_id} ### Description Retrieves a list of product prices associated with a specific customer partner ID. ### Method GET ### Endpoint `/oca/sale-workflow/pricelist/{partner_id}` ### Parameters #### Path Parameters - **partner_id** (integer) - Required - The unique identifier of the partner for whom to retrieve prices. #### Query Parameters None #### Request Body None ### Request Example ```bash curl -X GET "http://your.odoo/pricelist/$partner_id" -H "accept: /" -H "API-KEY: XYZ" ``` ### Response #### Success Response (200) - **products** (array) - A list of dictionaries, where each dictionary contains product information. - **id** (integer) - The product ID. - **price** (float) - The price of the product. #### Response Example ```json [ {"id": 123, "price": 99.99}, {"id": 456, "price": 49.50}, {"id": 789, "price": 199.00} ] ``` ### Notes The default response schema can be modified by configuring the 'Pricelist Cache Parser' in ir.exports. ``` -------------------------------- ### Document Title and Subtitle Alignment (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Styles for the main document title and subtitle, centering them horizontally on the page. ```CSS h1.title { text-align: center } h2.subtitle { text-align: center } ``` -------------------------------- ### Sidebar Title and Subtitle Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_recommendation/static/description/index.html These CSS rules style the titles and subtitles within sidebars, setting their font family to sans-serif and font weight to bold. Subtitles also get a larger font size. ```css p.sidebar-title { font-family: sans-serif ; font-weight: bold ; font-size: larger } p.sidebar-subtitle { font-family: sans-serif ; font-weight: bold } ``` -------------------------------- ### CSS: Definition Lists and Objects Source: https://github.com/oca/sale-workflow/blob/18.0/sale_force_invoiced/static/description/index.html Styles for definition lists and objects, including specific formatting for definition terms and handling of SVG or Flash objects. This ensures consistent rendering of these elements. ```css dl.docutils dd { margin-bottom: 0.5em } object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { overflow: hidden; } /* Uncomment (and remove this text!) to get bold-faced definition list terms */ /* dl.docutils dt { font-weight: bold } */ ``` -------------------------------- ### Document Element Spacing and Visibility (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_assortment/static/description/index.html This CSS snippet manages spacing and visibility for various document elements like first/last items, subtitles, and hidden content. It ensures proper layout and presentation. ```css .first { /* Override more specific margin styles with "! important". */ margin-top: 0 ! important } .last, .with-subtitle { margin-bottom: 0 ! important } .hidden { display: none } ``` -------------------------------- ### Abstract and Admonition Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_assortment/static/description/index.html This CSS snippet styles abstract sections and various admonition boxes (note, warning, error, etc.). It sets margins, borders, and specific font styles for titles. ```css div.abstract { margin: 2em 5em } div.abstract p.topic-title { font-weight: bold ; text-align: center } div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { margin: 2em ; border: medium outset ; padding: 1em } div.admonition p.admonition-title, div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif } div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title, .code .error { color: red ; font-weight: bold ; font-family: sans-serif } ``` -------------------------------- ### Configure Sale Automatic Workflow (XML) Source: https://context7.com/oca/sale-workflow/llms.txt An example of how to define and configure a 'Sale Workflow Process' record using XML in Odoo. This demonstrates setting various boolean fields to enable different automation steps for a sales process named 'Full Automation'. ```xml Full Automation ``` -------------------------------- ### Definition List and Object Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_order_product_assortment/static/description/index.html This CSS snippet styles definition lists and objects, particularly for SVG and Flash content. It adjusts margins for definition list descriptions and handles overflow for objects. ```css dl.docutils dd { margin-bottom: 0.5em } object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { overflow: hidden; } /* Uncomment (and remove this text!) to get bold-faced definition list terms */ /* dl.docutils dt { font-weight: bold } */ ``` -------------------------------- ### Odoo Invoice Plan Creation and Invoice Generation Source: https://context7.com/oca/sale-workflow/llms.txt Demonstrates creating an invoice plan for a sale order using a wizard, manually writing invoice plan details, and generating invoices for the next installment. This involves interacting with Odoo's sale and account modules. ```python # Example: Creating an invoice plan via wizard wizard = self.env['sale.create.invoice.plan'].create({ 'sale_id': sale_order.id, 'num_installment': 3, 'interval': 1, 'interval_type': 'month', }) wizard.sale_create_invoice_plan() # Manual invoice plan creation sale_order.write({ 'invoice_plan_ids': [ (0, 0, { 'installment': 1, 'plan_date': '2024-01-15', 'invoice_type': 'advance', 'percent': 30.0, }), (0, 0, { 'installment': 2, 'plan_date': '2024-02-15', 'invoice_type': 'installment', 'percent': 35.0, }), (0, 0, { 'installment': 3, 'plan_date': '2024-03-15', 'invoice_type': 'installment', 'percent': 35.0, }), ] }) # Create invoice for next installment next_plan = sale_order.invoice_plan_ids.filtered('to_invoice') if next_plan: wizard = self.env['sale.make.planned.invoice'].create({ 'advance_payment_method': 'percentage', }) wizard.with_context(active_id=sale_order.id).create_invoices_by_plan() ``` -------------------------------- ### Odoo Sale Invoice Plan Model Definition Source: https://context7.com/oca/sale-workflow/llms.txt Defines the 'sale.invoice.plan' model in Odoo, including fields for sales order linkage, customer, state, installment details, dates, invoice types, percentages, amounts, and related invoice information. It also includes computed fields for 'last', 'amount', 'invoiced', and 'to_invoice'. ```python from odoo import api, fields, models from odoo.exceptions import UserError, ValidationError class SaleInvoicePlan(models.Model): _name = "sale.invoice.plan" _description = "Invoice Planning Detail" _order = "installment" sale_id = fields.Many2one( comodel_name="sale.order", string="Sales Order", index=True, readonly=True, ondelete="cascade" ) partner_id = fields.Many2one( comodel_name="res.partner", string="Customer", related="sale_id.partner_id", store=True ) state = fields.Selection( string="Status", related="sale_id.state", store=True ) installment = fields.Integer() plan_date = fields.Date(required=True) invoice_type = fields.Selection( [("advance", "Advance"), ("installment", "Installment")], string="Type", required=True, default="installment" ) last = fields.Boolean( string="Last Installment", compute="_compute_last", help="Last installment uses remaining amount" ) percent = fields.Float( digits="Sales Invoice Plan Percent", help="Percent used to calculate invoice quantity" ) amount = fields.Float( digits="Product Price", compute="_compute_amount", inverse="_inverse_amount" ) invoice_move_ids = fields.Many2many( "account.move", string="Invoices", readonly=True ) invoiced = fields.Boolean( string="Invoice Created", compute="_compute_invoiced", store=True ) to_invoice = fields.Boolean( string="Next Invoice", compute="_compute_to_invoice" ) @api.depends("percent") def _compute_amount(self): for rec in self: amount_untaxed = rec.sale_id._origin.amount_untaxed if rec.invoiced: rec.amount = rec.amount_invoiced elif rec.last: # Last installment = remaining amount installments = rec.sale_id.invoice_plan_ids.filtered( lambda p: p.invoice_type == "installment" ) prev_amount = sum((installments - rec).mapped("amount")) rec.amount = amount_untaxed - prev_amount else: rec.amount = rec.percent * amount_untaxed / 100 ``` -------------------------------- ### Header and Footer Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html Styles for document headers and footers. It ensures they are cleared (not overlapping with other floated elements) and sets a smaller font size. ```CSS div.footer, div.header { clear: both; font-size: smaller } ``` -------------------------------- ### Subscript and Superscript Styling (CSS) Source: https://github.com/oca/sale-workflow/blob/18.0/sale_discount_display_amount/static/description/index.html These styles are for formatting subscript and superscript text. '.subscript' aligns text to the bottom and reduces its size, while '.superscript' aligns text to the top and also reduces its size. ```CSS .subscript { vertical-align: sub; font-size: smaller } .superscript { vertical-align: super; font-size: smaller } ```