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
12 changes: 6 additions & 6 deletions product_plm_import/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ Configuration

Update fields in the company (in the 'PLM I/F' tab):

- PLM Path: the absolute path to the PLM directory to fetch the files
from.
- PLM Notification Body: the text will be included in the notification
email body.
- PLM Notified Groups: assign groups to notify when a new file is
fetched from the PLM.
- PLM Path: the absolute path to the PLM directory to fetch the files
from.
- PLM Notification Body: the text will be included in the notification
email body.
- PLM Notified Groups: assign groups to notify when a new file is
fetched from the PLM.

The PLM-Product Mapping menu enables users to define product policies,
such as Product Type, Product Category, Routes, etc., which will be
Expand Down
2 changes: 1 addition & 1 deletion product_plm_import/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Product PLM Import",
"version": "16.0.1.0.0",
"version": "16.0.1.1.0",
"category": "Stock",
"license": "AGPL-3",
"author": "Quartile Limited",
Expand Down
2 changes: 1 addition & 1 deletion product_plm_import/models/plm_import_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def _send_plm_import_notification(self):
notified_groups = company.plm_notif_group_ids
notified_partners = notified_groups.users.partner_id
if not notified_partners:
return
continue
rec.message_subscribe(partner_ids=notified_partners.ids)
state_desc = rec._get_state_description(
"plm_product_state", rec.plm_product_state
Expand Down
18 changes: 16 additions & 2 deletions product_plm_import/models/plm_product_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

import fnmatch

from odoo import api, fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class PlmProductMapping(models.Model):
Expand Down Expand Up @@ -43,13 +44,26 @@ class PlmProductMapping(models.Model):
)
auto_create_lot = fields.Boolean()
lot_sequence_padding = fields.Integer()
lot_sequence_prefix = fields.Char()
lot_sequence_prefix = fields.Char(
help="Lot sequence prefix. Supports '{esc_code}' placeholder to use the ESC ID "
"of each PLM record (e.g. '{esc_code}')."
)
default_active = fields.Boolean(
help="Default value for active field of the created product."
)
company_id = fields.Many2one("res.company")
active = fields.Boolean(default=True)

@api.constrains("lot_sequence_prefix")
def _check_lot_sequence_prefix(self):
for record in self:
if not record.lot_sequence_prefix:
continue
try:
record.lot_sequence_prefix.format(esc_code="")
except (ValueError, KeyError):
raise ValidationError(_("Lot Sequence Prefix is invalid.")) from None

@api.onchange("product_type")
def onchange_product_type(self):
if self.product_type != "product":
Expand Down
11 changes: 7 additions & 4 deletions product_plm_import/models/product_plm.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def _get_uom(self):

def _create_product(self):
self.ensure_one()
product = self.env["product.product"]
description_purchase = self._get_description_purchase()
uom = self._get_uom()
mapping = self.mapping_id
Expand All @@ -113,12 +112,12 @@ def _create_product(self):
"is_draft": True,
}
try:
product = self.env["product.product"].create(vals)
return self.env["product.product"].create(vals)
except Exception as e:
_logger.error(
"ProductPlm._create_product - failed to create product: %s", str(e)
)
return product
return self.env["product.product"]

@api.model
def _get_create_products_domain(self):
Expand All @@ -144,7 +143,11 @@ def create_products(self, batch_size=30):
if mapping.lot_sequence_padding:
product.lot_sequence_id.padding = mapping.lot_sequence_padding
if mapping.lot_sequence_prefix:
product.lot_sequence_id.prefix = mapping.lot_sequence_prefix
prefix = mapping.lot_sequence_prefix.format(
esc_code=plm_rec.esc_code or "",
)
if prefix:
product.lot_sequence_id.prefix = prefix
product.product_tmpl_id.active = mapping.default_active
plm_rec.write({"state": "done", "product_id": product.id})
# This step fails with CasheMiss error in case product creation in
Expand Down
7 changes: 4 additions & 3 deletions product_plm_import/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z 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
customize this style sheet.
Expand Down Expand Up @@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* 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 @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

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

span.section-subtitle {
Expand Down
1 change: 1 addition & 0 deletions product_plm_import/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_product_plm
54 changes: 54 additions & 0 deletions product_plm_import/tests/test_product_plm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestProductPlm(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env["ir.config_parameter"].set_param(
"product_lot_sequence.policy", "product"
)
cls.item_type = cls.env["plm.item.type"].create({"name": "Test PCBA"})
cls.mapping = cls.env["plm.product.mapping"].create(
{
"item_type_id": cls.item_type.id,
"product_type": "product",
"product_categ_id": cls.env.ref("product.product_category_all").id,
"tracking": "serial",
"auto_create_lot": True,
}
)
cls.plm_rec = cls.env["product.plm"].create(
{
"part_number": "TEST-001",
"name": "Test Product",
"mapping_id": cls.mapping.id,
"company_id": cls.env.company.id,
"esc_code": "ESC123",
}
)

def test_lot_sequence_prefix_valid(self):
self.mapping.write({"lot_sequence_prefix": "{esc_code}"})
self.mapping.write({"lot_sequence_prefix": "STATIC"})
self.mapping.write({"lot_sequence_prefix": False})
with self.assertRaises(ValidationError):
self.mapping.write({"lot_sequence_prefix": "{invalid_key}"})
with self.assertRaises(ValidationError):
self.mapping.write({"lot_sequence_prefix": "{"})

def test_create_products_prefix_from_esc_code(self):
"""create_products() sets lot sequence prefix from ESC ID."""
self.mapping.write({"lot_sequence_prefix": "{esc_code}"})
self.env["product.plm"].create_products()
self.assertEqual(self.plm_rec.state, "done")
self.assertEqual(self.plm_rec.product_id.lot_sequence_id.prefix, "ESC123")

def test_create_products_no_prefix_without_esc_code(self):
"""create_products() skips prefix when ESC ID is absent."""
self.mapping.write({"lot_sequence_prefix": "{esc_code}"})
self.plm_rec.write({"esc_code": False})
self.env["product.plm"].create_products()
self.assertEqual(self.plm_rec.state, "done")
self.assertFalse(self.plm_rec.product_id.lot_sequence_id.prefix)