Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions sale_elaboration/README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

================
Sale Elaboration
================
Expand All @@ -7,13 +11,13 @@ Sale Elaboration
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e9e6fe3b6ec09b08497502643d0520ad12df2d3458e119f7493b406097d6ee90
!! source digest: sha256:cc865ea78ca02010b937cb1efe667a70e78a45925709c11885caa5c92452df3c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github
Expand Down Expand Up @@ -55,6 +59,21 @@ To configure this module you need to:
or *Display Elaboration notes on Picking Operations* if you want to show
elaborations on Picking Operations.

You can configure elaboration profiles as well. These profiles are a set of elaborations
that are available for chosen products or categories. When the salesman chooses the
elaboration in sales line, only those from the set for that product will be available.

To set the profile globally for a product category:

#. Go to *Inventory > Configuration > Product Categories* and choose one.
#. In the **Logistics** sections, you can set the desired **Elaboration profile**.

If you want to set an specific elaboration profile for a product:

#. Go to *Inventory > Products > Products* and choose one.
#. In the **Sales** tab, you'll find an **Elaboration** section where you can set the
**Elaboration profile** for that specific product.

Usage
=====

Expand Down
1 change: 1 addition & 0 deletions sale_elaboration/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"reports/report_base.xml",
"reports/report_deliveryslip.xml",
"reports/report_picking_operations.xml",
"views/product_category_views.xml",
],
"pre_init_hook": "pre_init_hook",
"maintainers": ["CarlosRoca13", "rafaelbn", "sergio-teruel", "yajo"],
Expand Down
1 change: 1 addition & 0 deletions sale_elaboration/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import product
from . import product_category
from . import product_elaboration
from . import product_elaboration_mixin
from . import product_elaboration_profile
Expand Down
4 changes: 3 additions & 1 deletion sale_elaboration/models/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ class ProductProduct(models.Model):
_inherit = "product.product"

elaboration_profile_id = fields.Many2one(
comodel_name="product.elaboration.profile", ondelete="restrict"
comodel_name="product.elaboration.profile",
ondelete="restrict",
help="Keep this field empty to use the default value from the product category.",
)
11 changes: 11 additions & 0 deletions sale_elaboration/models/product_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2025 Moduon Team S.L. <info@moduon.team>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models


class ProductCategory(models.Model):
_inherit = "product.category"

elaboration_profile_id = fields.Many2one(
comodel_name="product.elaboration.profile", string="Elaboration Profile"
)
1 change: 1 addition & 0 deletions sale_elaboration/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class ProductTemplate(models.Model):
compute="_compute_elaboration_profile_id",
inverse="_inverse_elaboration_profile_id",
store=True,
help="Keep this field empty to use the default value from the product category.",
)

@api.depends("product_variant_ids", "product_variant_ids.elaboration_profile_id")
Expand Down
13 changes: 12 additions & 1 deletion sale_elaboration/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class SaleOrderLine(models.Model):
date_order = fields.Datetime(related="order_id.date_order", string="Date")
route_id = fields.Many2one(compute="_compute_route_id", store=True, readonly=False)
elaboration_profile_id = fields.Many2one(
related="product_id.elaboration_profile_id"
comodel_name="product.elaboration.profile",
compute="_compute_elaboration_profile_id",
)
elaboration_price_unit = fields.Float(
"Elab. Price", compute="_compute_elaboration_price_unit", store=True
Expand All @@ -59,6 +60,16 @@ class SaleOrderLine(models.Model):
help=("Dummy field to be able to find prepared lines"),
)

@api.depends("product_id")
def _compute_elaboration_profile_id(self):
"""Order of applicability: product profile > category profile > no profile"""
self.elaboration_profile_id = False
for line in self.filtered("product_id"):
line.elaboration_profile_id = (
line.product_id.elaboration_profile_id
or line.product_id.categ_id.elaboration_profile_id
)

def get_elaboration_stock_route(self):
self.ensure_one()
return self.elaboration_ids.route_ids[:1]
Expand Down
15 changes: 15 additions & 0 deletions sale_elaboration/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,18 @@ To configure this module you need to:
notes on Delivery Slips* if you want to show elaborations on Delivery Slips
or *Display Elaboration notes on Picking Operations* if you want to show
elaborations on Picking Operations.

You can configure elaboration profiles as well. These profiles are a set of elaborations
that are available for chosen products or categories. When the salesman chooses the
elaboration in sales line, only those from the set for that product will be available.

To set the profile globally for a product category:

#. Go to *Inventory > Configuration > Product Categories* and choose one.
#. In the **Logistics** sections, you can set the desired **Elaboration profile**.

If you want to set an specific elaboration profile for a product:

#. Go to *Inventory > Products > Products* and choose one.
#. In the **Sales** tab, you'll find an **Elaboration** section where you can set the
**Elaboration profile** for that specific product.
44 changes: 32 additions & 12 deletions sale_elaboration/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Sale Elaboration</title>
<title>README.rst</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -360,16 +360,21 @@
</style>
</head>
<body>
<div class="document" id="sale-elaboration">
<h1 class="title">Sale Elaboration</h1>
<div class="document">


<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="sale-elaboration">
<h1>Sale Elaboration</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e9e6fe3b6ec09b08497502643d0520ad12df2d3458e119f7493b406097d6ee90
!! source digest: sha256:cc865ea78ca02010b937cb1efe667a70e78a45925709c11885caa5c92452df3c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/16.0/sale_elaboration"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-16-0/sale-workflow-16-0-sale_elaboration"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/16.0/sale_elaboration"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-16-0/sale-workflow-16-0-sale_elaboration"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module extends the functionality of sales orders to allow to set an
elaboration on lines that will add an extra order line with an elaboration
product linked to it when the delivery order is validated.</p>
Expand All @@ -391,7 +396,7 @@ <h1 class="title">Sale Elaboration</h1>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
<p>To configure this module you need to:</p>
<ol class="arabic simple">
<li>Go to <em>Sale &gt; Configuration &gt; Products &gt; Sale Elaboration</em>.</li>
Expand All @@ -403,9 +408,23 @@ <h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
or <em>Display Elaboration notes on Picking Operations</em> if you want to show
elaborations on Picking Operations.</li>
</ol>
<p>You can configure elaboration profiles as well. These profiles are a set of elaborations
that are available for chosen products or categories. When the salesman chooses the
elaboration in sales line, only those from the set for that product will be available.</p>
<p>To set the profile globally for a product category:</p>
<ol class="arabic simple">
<li>Go to <em>Inventory &gt; Configuration &gt; Product Categories</em> and choose one.</li>
<li>In the <strong>Logistics</strong> sections, you can set the desired <strong>Elaboration profile</strong>.</li>
</ol>
<p>If you want to set an specific elaboration profile for a product:</p>
<ol class="arabic simple">
<li>Go to <em>Inventory &gt; Products &gt; Products</em> and choose one.</li>
<li>In the <strong>Sales</strong> tab, you’ll find an <strong>Elaboration</strong> section where you can set the
<strong>Elaboration profile</strong> for that specific product.</li>
</ol>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<h2><a class="toc-backref" href="#toc-entry-2">Usage</a></h2>
<ol class="arabic simple">
<li>Go to <em>Sale &gt; Quotations</em>.</li>
<li>Create a sales order.</li>
Expand All @@ -419,23 +438,23 @@ <h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
</ol>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<h2><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sale-workflow/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_elaboration%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<h2><a class="toc-backref" href="#toc-entry-4">Credits</a></h2>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<h3><a class="toc-backref" href="#toc-entry-5">Authors</a></h3>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<h3><a class="toc-backref" href="#toc-entry-6">Contributors</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Sergio Teruel</li>
Expand All @@ -449,7 +468,7 @@ <h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand All @@ -464,5 +483,6 @@ <h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
</div>
</div>
</div>
</div>
</body>
</html>
29 changes: 29 additions & 0 deletions sale_elaboration/tests/test_sale_elaboration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2018 Tecnativa - Sergio Teruel
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import Command
from odoo.tests import Form, tagged

from odoo.addons.account.tests.common import AccountTestInvoicingCommon
Expand All @@ -11,9 +12,21 @@ class TestSaleElaboration(AccountTestInvoicingCommon):
def setUpClass(cls):
super().setUpClass()
cls.Elaboration = cls.env["product.elaboration"]
cls.ElaborationProfile = cls.env["product.elaboration.profile"]
cls.category_1 = cls.env["product.category"].create({"name": "Meat"})
cls.category_2 = cls.env["product.category"].create({"name": "Fish"})
cls.product = cls.env["product.product"].create(
{"name": "test", "tracking": "none", "list_price": 1000}
)
cls.product_2 = cls.env["product.product"].create(
{"name": "test 2", "tracking": "none", "list_price": 1000}
)
cls.product_3 = cls.env["product.product"].create(
{"name": "test 2", "tracking": "none", "list_price": 1000}
)
cls.product.categ_id = cls.category_1
cls.product_2.categ_id = cls.category_2
cls.product_3.categ_id = cls.category_1
cls.product_elaboration_A = cls.env["product.product"].create(
{
"name": "Product Elaboration A",
Expand Down Expand Up @@ -65,9 +78,25 @@ def setUpClass(cls):
"product_id": cls.product_elaboration_B.id,
}
)
cls.elaboration_profile_a = cls.ElaborationProfile.create(
{
"name": "Elaboration Profile A",
"elaboration_ids": [
Command.set([cls.elaboration_a.id, cls.elaboration_b.id])
],
}
)
cls.elaboration_profile_b = cls.ElaborationProfile.create(
{
"name": "Elaboration Profile B",
"elaboration_ids": [Command.set(cls.elaboration_a.ids)],
}
)
cls.product.elaboration_profile_id = cls.elaboration_profile_a
cls.order = cls._create_sale_order(
cls, [(cls.product, 10, [cls.elaboration_a])]
)
cls.category_1.elaboration_profile_id = cls.elaboration_profile_b

def _create_sale_order(self, products_info):
order_form = Form(self.env["sale.order"])
Expand Down
16 changes: 16 additions & 0 deletions sale_elaboration/views/product_category_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record
model="ir.ui.view"
id="sale_elaboration_product_category_view_form_inherit_elaboration_id"
>
<field name="name">product.category.view.form.sale.elaboration</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view" />
<field name="arch" type="xml">
<xpath expr="//group[@name='logistics']" position="inside">
<field name="elaboration_profile_id" />
</xpath>
</field>
</record>
</odoo>