Skip to content
Open
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
40 changes: 24 additions & 16 deletions purchase_order_secondary_unit/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Purchase Order Secondary Unit
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:2b71909b287e9e5c437aea172c4c165ed1bee7b3e981d1c44d99c8bfaae5740d
!! source digest: sha256:3060215436f72f80719f51c8b70f79ff92b39bde293b9739bd47588e74ad8b30
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down Expand Up @@ -81,13 +81,13 @@ To use this module you need to:

**Vendor Pricelist Integration**

- When adding a vendor to a product's pricelist (via *Purchase tab >
Vendors*), the secondary unit of measure is automatically defaulted
from the product variant's purchase secondary UOM, or from the
product template if not set on the variant.
- When a new vendor pricelist record is created from purchase order
confirmation, the secondary UOM from the purchase order line is
automatically stored in the vendor pricelist entry.
- When adding a vendor to a product's pricelist (via *Purchase tab >
Vendors*), the secondary unit of measure is automatically defaulted
from the product variant's purchase secondary UOM, or from the product
template if not set on the variant.
- When a new vendor pricelist record is created from purchase order
confirmation, the secondary UOM from the purchase order line is
automatically stored in the vendor pricelist entry.

Known issues / Roadmap
======================
Expand Down Expand Up @@ -118,17 +118,17 @@ Authors
Contributors
------------

- `Tecnativa <https://www.tecnativa.com>`__:
- `Tecnativa <https://www.tecnativa.com>`__:

- Sergio Teruel
- Ernesto Tejeda
- Sergio Teruel
- Ernesto Tejeda

- Nikul Chaudhary <nikulchaudhary2112@gmail.com>
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
- Miguel Ángel Gómez <miguel.gomez@braintec.com>
- `Quartile <https://www.quartile.co>`__:
- Nikul Chaudhary <nikulchaudhary2112@gmail.com>
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
- Miguel Ángel Gómez <miguel.gomez@braintec.com>
- `Quartile <https://www.quartile.co>`__:

- Yoshi Tashiro
- Yoshi Tashiro

Maintainers
-----------
Expand All @@ -143,6 +143,14 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-sergio-teruel| image:: https://github.com/sergio-teruel.png?size=40px
:target: https://github.com/sergio-teruel
:alt: sergio-teruel

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-sergio-teruel|

This module is part of the `OCA/purchase-workflow <https://github.com/OCA/purchase-workflow/tree/18.0/purchase_order_secondary_unit>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions purchase_order_secondary_unit/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"category": "Purchase",
"website": "https://github.com/OCA/purchase-workflow",
"author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["sergio-teruel"],
"license": "AGPL-3",
"application": False,
"installable": True,
Expand Down
13 changes: 13 additions & 0 deletions purchase_order_secondary_unit/models/product_supplierinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, fields, models
from odoo.tools import float_compare


class ProductSupplierinfo(models.Model):
Expand Down Expand Up @@ -30,8 +31,20 @@ def _compute_secondary_uom_price(self):

@api.onchange("secondary_uom_price")
def _inverse_secondary_uom_price(self):
precision = self.env["decimal.precision"].precision_get("Product Price")
for rec in self:
if rec.secondary_uom_id:
expected_secondary_price = rec.price * rec.secondary_uom_id.factor
if (
rec.price
and float_compare(
rec.secondary_uom_price,
expected_secondary_price,
precision_digits=precision,
)
== 0
):
continue
rec.price = rec.secondary_uom_price / rec.secondary_uom_id.factor

@api.onchange("product_tmpl_id", "product_id")
Expand Down
13 changes: 13 additions & 0 deletions purchase_order_secondary_unit/models/purchase_order.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright 2018 Tecnativa - Sergio Teruel
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.tools import float_compare


class PurchaseOrder(models.Model):
Expand Down Expand Up @@ -58,8 +59,20 @@ def _compute_secondary_uom_price(self):

@api.onchange("secondary_uom_price")
def _inverse_secondary_uom_price(self):
precision = self.env["decimal.precision"].precision_get("Product Price")
for rec in self:
if rec.secondary_uom_id:
expected_secondary_price = rec.price_unit * rec.secondary_uom_id.factor
if (
rec.price_unit
and float_compare(
rec.secondary_uom_price,
expected_secondary_price,
precision_digits=precision,
)
== 0
):
continue
rec.price_unit = rec.secondary_uom_price / rec.secondary_uom_id.factor

@api.onchange("product_uom")
Expand Down
62 changes: 31 additions & 31 deletions purchase_order_secondary_unit/static/description/index.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
<title>Purchase Order Secondary Unit</title>
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

Expand Down Expand Up @@ -275,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: gray; } /* line numbers */
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -301,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic, pre.problematic {
span.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -367,9 +367,9 @@ <h1 class="title">Purchase Order Secondary Unit</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:2b71909b287e9e5c437aea172c4c165ed1bee7b3e981d1c44d99c8bfaae5740d
!! source digest: sha256:3060215436f72f80719f51c8b70f79ff92b39bde293b9739bd47588e74ad8b30
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.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/purchase-workflow/tree/18.0/purchase_order_secondary_unit"><img alt="OCA/purchase-workflow" src="https://img.shields.io/badge/github-OCA%2Fpurchase--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/purchase-workflow-18-0/purchase-workflow-18-0-purchase_order_secondary_unit"><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/purchase-workflow&amp;target_branch=18.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" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" 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" href="https://github.com/OCA/purchase-workflow/tree/18.0/purchase_order_secondary_unit"><img alt="OCA/purchase-workflow" src="https://img.shields.io/badge/github-OCA%2Fpurchase--workflow-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/purchase-workflow-18-0/purchase-workflow-18-0-purchase_order_secondary_unit"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runboat.odoo-community.org/builds?repo=OCA/purchase-workflow&amp;target_branch=18.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 purchase orders to allow buy
products in secondary unit of distinct category.</p>
<p>Users can enter quantities and prices in secondary units on purchase
Expand All @@ -380,28 +380,28 @@ <h1 class="title">Purchase Order Secondary Unit</h1>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a><ul>
<li><a class="reference internal" href="#settings-visibility" id="toc-entry-2">Settings Visibility</a></li>
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a><ul>
<li><a class="reference internal" href="#settings-visibility" id="id2">Settings Visibility</a></li>
</ul>
</li>
<li><a class="reference internal" href="#usage" id="toc-entry-3">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-4">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li>
<li><a class="reference internal" href="#usage" id="id3">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<h1><a class="toc-backref" href="#id1">Configuration</a></h1>
<p>For configuration of displaying secondary unit information in purchase
reports and the Purchase Order portal, see the guidelines provided in
product_secondary_unit.</p>
<div class="section" id="settings-visibility">
<h2><a class="toc-backref" href="#toc-entry-2">Settings Visibility</a></h2>
<h2><a class="toc-backref" href="#id2">Settings Visibility</a></h2>
<p>When installing this module, all internal users are automatically added
to the <tt class="docutils literal">product_secondary_unit.group_purchase_secondary_unit</tt> security
group. This makes the Purchase-related “Hide Secondary Qty Column” and
Expand All @@ -418,7 +418,7 @@ <h2><a class="toc-backref" href="#toc-entry-2">Settings Visibility</a></h2>
</div>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-3">Usage</a></h1>
<h1><a class="toc-backref" href="#id3">Usage</a></h1>
<p>To use this module you need to:</p>
<ol class="arabic simple">
<li>Go to a <em>Product &gt; General Information tab</em>.</li>
Expand All @@ -432,38 +432,38 @@ <h1><a class="toc-backref" href="#toc-entry-3">Usage</a></h1>
<ul class="simple">
<li>When adding a vendor to a product’s pricelist (via <em>Purchase tab &gt;
Vendors</em>), the secondary unit of measure is automatically defaulted
from the product variant’s purchase secondary UOM, or from the
product template if not set on the variant.</li>
from the product variant’s purchase secondary UOM, or from the product
template if not set on the variant.</li>
<li>When a new vendor pricelist record is created from purchase order
confirmation, the secondary UOM from the purchase order line is
automatically stored in the vendor pricelist entry.</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-4">Known issues / Roadmap</a></h1>
<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1>
<p>Updating existing vendor pricelist records from purchase order
confirmation does not currently support secondary UOM or secondary UOM
pricing. This is not included in the current scope and may be considered
in future improvements.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#id5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/purchase-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/purchase-workflow/issues/new?body=module:%20purchase_order_secondary_unit%0Aversion:%2018.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-6">Credits</a></h1>
<h1><a class="toc-backref" href="#id6">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
<h2><a class="toc-backref" href="#id7">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<h2><a class="toc-backref" href="#id8">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Sergio Teruel</li>
Expand All @@ -480,14 +480,14 @@ <h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
<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" />
</a>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/sergio-teruel"><img alt="sergio-teruel" src="https://github.com/sergio-teruel.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/purchase-workflow/tree/18.0/purchase_order_secondary_unit">OCA/purchase-workflow</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ def test_supplierinfo_secondary_uom_price_inverse(self):
# secondary_uom_price = 140, factor = 0.7, price = 200
self.assertEqual(self.supplierinfo.price, 200.0)

def test_supplierinfo_keeps_price_when_secondary_price_rounds(self):
secondary_unit = self.env["product.secondary.unit"].create(
{
"name": "unit-900",
"uom_id": self.product_uom_unit.id,
"factor": 0.9,
"product_tmpl_id": self.product.product_tmpl_id.id,
}
)
supplierinfo_form = Form(
self.env["product.supplierinfo"].with_context(
default_product_tmpl_id=self.product.product_tmpl_id.id
)
)
supplierinfo_form.partner_id = self.partner
supplierinfo_form.price = 19.95
supplierinfo_form.secondary_uom_id = secondary_unit
self.assertAlmostEqual(supplierinfo_form.secondary_uom_price, 17.96)
self.assertAlmostEqual(supplierinfo_form.price, 19.95)

def test_supplierinfo_no_secondary_unit(self):
self.supplierinfo.secondary_uom_id = False
self.assertEqual(self.supplierinfo.secondary_uom_price, 0.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,32 @@ def test_purchase_order_secondary_uom_price(self):
# price_unit = 100, factor = 0.7, secondary_uom_price = 70
self.assertEqual(line.secondary_uom_price, 70.0)

def test_purchase_order_keeps_supplier_price_when_secondary_price_rounds(self):
secondary_unit = self.env["product.secondary.unit"].create(
{
"name": "unit-900",
"uom_id": self.product_uom_unit.id,
"factor": 0.9,
"product_tmpl_id": self.product.product_tmpl_id.id,
}
)
self.product.purchase_secondary_uom_id = secondary_unit
self.env["product.supplierinfo"].create(
{
"partner_id": self.partner.id,
"product_tmpl_id": self.product.product_tmpl_id.id,
"price": 19.95,
}
)
purchase_order = Form(self.purchase_order_obj)
purchase_order.partner_id = self.partner
with purchase_order.order_line.new() as line:
line.product_id = self.product
self.assertEqual(line.secondary_uom_qty, 1.0)
self.assertAlmostEqual(line.product_qty, 0.9)
self.assertAlmostEqual(line.secondary_uom_price, 17.96)
self.assertAlmostEqual(line.price_unit, 19.95)

def test_purchase_order_confirm_creates_supplierinfo_with_secondary_uom(self):
new_product = self.env["product.product"].create(
{
Expand Down
Loading