From 583e25e0922fb9090673ba0876be1e4dd5bcb350 Mon Sep 17 00:00:00 2001 From: xtremxpert Date: Fri, 29 Aug 2025 09:43:24 -0400 Subject: [PATCH] product_supplierinfo_tracking --- .../__manifest__.py.backup | 27 ++ .../models/product_supplier_info.py.backup | 63 +---- .../static/description/icon.png | Bin 13986 -> 3648 bytes .../views/product_view.xml | 13 - .../views/supplierinfo_pricelist.xml | 80 ++---- .../views/supplierinfo_pricelist.xml.backup | 91 ++++++ product_supplierinfo_pricing/__init__.py | 3 + product_supplierinfo_pricing/__manifest__.py | 24 ++ .../models/__init__.py | 3 + .../models/product_supplierinfo.py | 57 ++++ .../product_supplierinfo_pricing_views.xml | 35 +++ product_supplierinfo_tracking/__manifest__.py | 31 +- .../models/__init__.py | 2 +- .../models/product_supplier_info.py | 88 ++++++ .../static/description/icon.png | Bin 14547 -> 3648 bytes .../tests/__init__.py | 3 + .../test_product_supplierinfo_tracking.py | 266 ++++++++++++++++++ .../views/product_view.xml | 26 +- .../views/supplierinfo.xml | 27 ++ .../views/supplierinfo_pricelist.xml | 22 -- .../views/supplierinfo_pricelist.xml.backup | 91 ++++++ 21 files changed, 764 insertions(+), 188 deletions(-) create mode 100755 product_pricelist_supplierinfo_chatter/__manifest__.py.backup rename product_supplierinfo_tracking/models/product_supplierinfo.py => product_pricelist_supplierinfo_chatter/models/product_supplier_info.py.backup (59%) mode change 100755 => 100644 product_pricelist_supplierinfo_chatter/static/description/icon.png create mode 100644 product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml.backup create mode 100644 product_supplierinfo_pricing/__init__.py create mode 100644 product_supplierinfo_pricing/__manifest__.py create mode 100644 product_supplierinfo_pricing/models/__init__.py create mode 100644 product_supplierinfo_pricing/models/product_supplierinfo.py create mode 100644 product_supplierinfo_pricing/views/product_supplierinfo_pricing_views.xml create mode 100755 product_supplierinfo_tracking/models/product_supplier_info.py create mode 100644 product_supplierinfo_tracking/tests/__init__.py create mode 100644 product_supplierinfo_tracking/tests/test_product_supplierinfo_tracking.py create mode 100644 product_supplierinfo_tracking/views/supplierinfo.xml delete mode 100644 product_supplierinfo_tracking/views/supplierinfo_pricelist.xml create mode 100644 product_supplierinfo_tracking/views/supplierinfo_pricelist.xml.backup diff --git a/product_pricelist_supplierinfo_chatter/__manifest__.py.backup b/product_pricelist_supplierinfo_chatter/__manifest__.py.backup new file mode 100755 index 0000000..654d6a8 --- /dev/null +++ b/product_pricelist_supplierinfo_chatter/__manifest__.py.backup @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +{ + "name": "Product Supplier Info Chatter (Legacy)", + "version": "18.0.4.0.0", + "license": "AGPL-3", + "author": "Bemade", + "category": "Inventory/Purchase", + "depends": [ + "product", + "mail", + ], + "description": """ + Legacy module - use product_supplierinfo_chatter instead. + This module adds chatter functionality to supplier information, + providing tracking of price changes and communication history. + """, + "demo": [], + 'data': [ + 'views/product_view.xml', + 'views/supplierinfo_pricelist.xml', + ], + 'test': [], + 'installable': True, + 'active': False +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_supplierinfo_tracking/models/product_supplierinfo.py b/product_pricelist_supplierinfo_chatter/models/product_supplier_info.py.backup similarity index 59% rename from product_supplierinfo_tracking/models/product_supplierinfo.py rename to product_pricelist_supplierinfo_chatter/models/product_supplier_info.py.backup index 2f1e150..784bb78 100755 --- a/product_supplierinfo_tracking/models/product_supplierinfo.py +++ b/product_pricelist_supplierinfo_chatter/models/product_supplier_info.py.backup @@ -5,37 +5,18 @@ from markupsafe import Markup class ProductSupplierInfo(models.Model): - _name = "product.supplierinfo" _inherit = [ "product.supplierinfo", "mail.thread", "mail.activity.mixin" ] - # Commented out because breaking basic Odoo tests. See if this is really needed. - - # _sql_constraints = [("supplierinfo_product_tmpl_id_no_null", - # "CHECK((product_tmpl_id IS NOT NULL))", - # "Supplier pricelist need product template"), - # ] - - # This while avoid the database to save those record with lost product_tmpl_id - @api.depends("supplier_list_price", "supplier_discount_percent") - def _compute_price(self): - for rec in self: - rec.price = rec.supplier_list_price - ( - rec.supplier_list_price * rec.supplier_discount_percent / 100 - ) - - @api.depends("supplier_discount_percent") - def _inverse_price(self): - for rec in self: - discount = ( - rec.supplier_discount_percent if rec.supplier_discount_percent else 0 - ) - rec.supplier_list_price = (100 * rec.price) / (100 - discount) - - partner_id = fields.Many2one(tracking=True, domain=[("is_company", "=", True)]) + # We add tracking to the existing fields for chatter functionality + partner_id = fields.Many2one( + tracking=True, + domain=[("is_company", "=", True)] + ) + product_name = fields.Char(tracking=True) product_code = fields.Char(tracking=True) product_uom = fields.Many2one(tracking=True) @@ -47,35 +28,9 @@ class ProductSupplierInfo(models.Model): product_tmpl_id = fields.Many2one(tracking=True) delay = fields.Integer(tracking=True) - date_updated = fields.Date( - string="Last updated", - help="Date at which the supplier " + " list price was last updated.", - ) - - purchasing_notes = fields.Text(tracking=True, string="Purchasing Notes") - - supplier_list_price = fields.Float( - string="Supplier List Price", - digits="Product Price", - tracking=True, - help=""" - This the supplier list price to which supplier discounts are applied, if - any, and the net price if no supplier discounts are to be applied - """, - ) - - supplier_discount_percent = fields.Float( - string="Supplier discount (%)", digits="Product Price", tracking=True, default=0 - ) - - price = fields.Float( - compute="_compute_price", - inverse="_inverse_price", - string="Supplier Price", - digits="Product Price", - help="This price will be considered as a price for the supplier UoM if any or " - "the default Unit of Measure of the product otherwise", - store=True, + purchasing_notes = fields.Text( + tracking=True, + string="Purchasing Notes" ) def _generate_chatter(self, vals, operation): diff --git a/product_pricelist_supplierinfo_chatter/static/description/icon.png b/product_pricelist_supplierinfo_chatter/static/description/icon.png old mode 100755 new mode 100644 index 0130194366529344db9db51e138a7c1f25cb0c80..1a0c0fb0050e7f95fe1010bafdd7c5ba621b1ebf GIT binary patch literal 3648 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 literal 13986 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 diff --git a/product_pricelist_supplierinfo_chatter/views/product_view.xml b/product_pricelist_supplierinfo_chatter/views/product_view.xml index c3fea2e..bd7cce4 100755 --- a/product_pricelist_supplierinfo_chatter/views/product_view.xml +++ b/product_pricelist_supplierinfo_chatter/views/product_view.xml @@ -1,18 +1,5 @@ - - - product.supplierinfo.tree.no.edit - product.supplierinfo - - - - - - - - - product.template.form.view.landed diff --git a/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml b/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml index 9d72f74..1881be4 100644 --- a/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml +++ b/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml @@ -1,74 +1,26 @@ + + + product.supplierinfo.tree.no.edit + product.supplierinfo + + + + + + + + supplierinfo.pricelist.chatter product.supplierinfo + -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
-
+ + +
diff --git a/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml.backup b/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml.backup new file mode 100644 index 0000000..89ad638 --- /dev/null +++ b/product_pricelist_supplierinfo_chatter/views/supplierinfo_pricelist.xml.backup @@ -0,0 +1,91 @@ + + + + + + supplierinfo.pricelist.chatter + product.supplierinfo + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+ + + + product.supplierinfo.company.groups + product.supplierinfo + + + + base.group_multi_company + + + + +
+ +
\ No newline at end of file diff --git a/product_supplierinfo_pricing/__init__.py b/product_supplierinfo_pricing/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/product_supplierinfo_pricing/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/product_supplierinfo_pricing/__manifest__.py b/product_supplierinfo_pricing/__manifest__.py new file mode 100644 index 0000000..cbd0689 --- /dev/null +++ b/product_supplierinfo_pricing/__manifest__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +{ + "name": "Product Supplier Info Pricing", + "version": "18.0.1.0.0", + "license": "AGPL-3", + "author": "Bemade", + "category": "Inventory/Purchase", + "depends": [ + "product", + ], + "description": """ + This module adds additional pricing fields to supplier information, + including supplier list price, discount percentage, and calculated price. + """, + "demo": [], + 'data': [ + 'views/product_supplierinfo_pricing_views.xml', + ], + 'test': [], + 'installable': True, + 'active': False +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_supplierinfo_pricing/models/__init__.py b/product_supplierinfo_pricing/models/__init__.py new file mode 100644 index 0000000..25e2824 --- /dev/null +++ b/product_supplierinfo_pricing/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import product_supplierinfo diff --git a/product_supplierinfo_pricing/models/product_supplierinfo.py b/product_supplierinfo_pricing/models/product_supplierinfo.py new file mode 100644 index 0000000..4291fe8 --- /dev/null +++ b/product_supplierinfo_pricing/models/product_supplierinfo.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api + + +class ProductSupplierInfo(models.Model): + _inherit = "product.supplierinfo" + + date_updated = fields.Date( + string="Last updated", + help="Date at which the supplier list price was last updated.", + ) + + purchasing_notes = fields.Text( + string="Purchasing Notes" + ) + + supplier_list_price = fields.Float( + string="Supplier List Price", + digits="Product Price", + help="""This the supplier list price to which supplier discounts are applied, if + any, and the net price if no supplier discounts are to be applied""", + ) + + supplier_discount_percent = fields.Float( + string="Supplier discount (%)", + digits="Product Price", + default=0 + ) + + price = fields.Float( + compute="_compute_price", + inverse="_inverse_price", + string="Supplier Price", + digits="Product Price", + help="This price will be considered as a price for the supplier UoM if any or " + "the default Unit of Measure of the product otherwise", + store=True, + ) + + @api.depends("supplier_list_price", "supplier_discount_percent") + def _compute_price(self): + for rec in self: + rec.price = rec.supplier_list_price - ( + rec.supplier_list_price * rec.supplier_discount_percent / 100 + ) + + @api.depends("supplier_discount_percent") + def _inverse_price(self): + for rec in self: + discount = ( + rec.supplier_discount_percent if rec.supplier_discount_percent else 0 + ) + if discount >= 100: + rec.supplier_list_price = 0 + else: + rec.supplier_list_price = (100 * rec.price) / (100 - discount) diff --git a/product_supplierinfo_pricing/views/product_supplierinfo_pricing_views.xml b/product_supplierinfo_pricing/views/product_supplierinfo_pricing_views.xml new file mode 100644 index 0000000..b04f4b1 --- /dev/null +++ b/product_supplierinfo_pricing/views/product_supplierinfo_pricing_views.xml @@ -0,0 +1,35 @@ + + + + + + supplierinfo.pricing.form + product.supplierinfo + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/product_supplierinfo_tracking/__manifest__.py b/product_supplierinfo_tracking/__manifest__.py index 3c90a0d..3e0c54e 100755 --- a/product_supplierinfo_tracking/__manifest__.py +++ b/product_supplierinfo_tracking/__manifest__.py @@ -1,31 +1,11 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - { "name": "Product Supplierinfo Tracking", - "version": "18.0.2.0.5", + "version": "18.0.3.0.0", "license": "AGPL-3", "author": "Bemade", - "category": "Purchase", + "category": "Tools", "depends": [ "base", "product", @@ -35,14 +15,13 @@ "mrp", ], "description": """ - This module extends basic inventory and pricelist management in - OpenERP to include support for supplierinfo tracking. - + This module extends basic inventory support for supplierinfo chatter making price + updates visible in the chatter. """, "demo": [], 'data': [ 'views/product_view.xml', - 'views/supplierinfo_pricelist.xml', + 'views/supplierinfo.xml', ], 'test': [], 'installable': True, diff --git a/product_supplierinfo_tracking/models/__init__.py b/product_supplierinfo_tracking/models/__init__.py index d29af9a..937da63 100644 --- a/product_supplierinfo_tracking/models/__init__.py +++ b/product_supplierinfo_tracking/models/__init__.py @@ -1 +1 @@ -from . import product_supplierinfo \ No newline at end of file +from . import product_supplier_info \ No newline at end of file diff --git a/product_supplierinfo_tracking/models/product_supplier_info.py b/product_supplierinfo_tracking/models/product_supplier_info.py new file mode 100755 index 0000000..1ae9bae --- /dev/null +++ b/product_supplierinfo_tracking/models/product_supplier_info.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api +from markupsafe import Markup + + +class ProductSupplierInfo(models.Model): + _name = "product.supplierinfo" + _inherit = ["product.supplierinfo", "mail.thread", "mail.activity.mixin"] + + # Commented out because breaking basic Odoo tests. See if this is really needed. + + # _sql_constraints = [("supplierinfo_product_tmpl_id_no_null", + # "CHECK((product_tmpl_id IS NOT NULL))", + # "Supplier pricelist need product template"), + # ] + + # We add tracking to the fields that are displayed in the chatter + partner_id = fields.Many2one( + tracking=True, + domain=[("is_company", "=", True)] + ) + + product_name = fields.Char(tracking=True) + product_code = fields.Char(tracking=True) + product_uom = fields.Many2one(tracking=True) + min_qty = fields.Float(tracking=True) + currency_id = fields.Many2one(tracking=True) + date_start = fields.Date(tracking=True) + date_end = fields.Date(tracking=True) + product_id = fields.Many2one(tracking=True) + product_tmpl_id = fields.Many2one(tracking=True) + delay = fields.Integer(tracking=True) + + + def _generate_chatter(self, vals, operation): + if len(self) == 1 and self.product_tmpl_id: + msg = "" + headmsg = ( + f"" + f"Price {operation} for {self.product_id.name} :
" + ) + if self.min_qty > 0: + msg += f"
  • Minimum qty : {self.min_qty}
  • " + if self.date_start: + msg += f"
  • Starting : {self.date_start}
  • " + if self.date_end: + msg += f"
  • Ending : {self.date_end}
  • " + if msg: + msg = headmsg + "
      " + msg + "
    " + else: + msg = headmsg + for change in vals: + msg += f"{change} --> {vals[change]}
    " + # Should always be there + if self.product_tmpl_id: + self.product_tmpl_id.message_post( + body=Markup(msg), + ) + # only for variant + if self.product_id: + self.product_id.message_post(body=Markup(msg)) + + + def write(self, vals): + res = super(ProductSupplierInfo, self).write(vals) + self._generate_chatter(vals, "modify") + return res + + def supplierinfo_show_details(self): + """ + Action to open product.supplierinfo (pricelist) in its own windows and not in a javascript + popup to avoid loosing product_tmpl_id. We rely on both context and domain to pass the + information + """ + return { + "name": "Supplier price", + "view_type": "form", + "view_mode": "form", + "res_id": self.id, + "context": self.env.context, + "res_model": "product.supplierinfo", + "domain": [ + ("product_tmpl_id", "=", self.product_tmpl_id.id), + ("product_id", "=", self.product_id.id if self.product_id else False), + ], + "type": "ir.actions.act_window", + } diff --git a/product_supplierinfo_tracking/static/description/icon.png b/product_supplierinfo_tracking/static/description/icon.png index 4a8f3595cce5d05c9b82efaba6e24c74b43c0162..1a0c0fb0050e7f95fe1010bafdd7c5ba621b1ebf 100644 GIT binary patch literal 3648 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 literal 14547 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 D;+c%? diff --git a/product_supplierinfo_tracking/tests/__init__.py b/product_supplierinfo_tracking/tests/__init__.py new file mode 100644 index 0000000..5765e7e --- /dev/null +++ b/product_supplierinfo_tracking/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import test_product_supplierinfo_tracking diff --git a/product_supplierinfo_tracking/tests/test_product_supplierinfo_tracking.py b/product_supplierinfo_tracking/tests/test_product_supplierinfo_tracking.py new file mode 100644 index 0000000..abd9464 --- /dev/null +++ b/product_supplierinfo_tracking/tests/test_product_supplierinfo_tracking.py @@ -0,0 +1,266 @@ +# -*- coding: utf-8 -*- + +from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError +from markupsafe import Markup + + +class TestProductSupplierinfoTracking(TransactionCase): + + def setUp(self): + super().setUp() + + # Use existing data to avoid database constraint issues + self.partner_supplier = self.env['res.partner'].create({ + 'name': 'Test Supplier', + 'is_company': True, + 'supplier_rank': 1, + }) + + # Use first available product template and variant + self.product_template = self.env['product.template'].search([], limit=1) + if not self.product_template: + self.skipTest("No product template available for testing") + + self.product_variant = self.product_template.product_variant_ids[0] if self.product_template.product_variant_ids else None + + self.currency_usd = self.env.ref('base.USD') + self.uom_unit = self.env.ref('uom.product_uom_unit') + + def test_supplierinfo_tracking_fields(self): + """Test that tracking is enabled on all expected fields""" + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'min_qty': 10.0, + 'price': 100.0, + 'currency_id': self.currency_usd.id, + 'product_name': 'Supplier Product Name', + 'product_code': 'SUP001', + 'delay': 5, + }) + + # Check that the model inherits from mail.thread + self.assertTrue(hasattr(supplierinfo, 'message_ids')) + self.assertTrue(hasattr(supplierinfo, 'activity_ids')) + + # Verify tracking fields are properly set + tracked_fields = [ + 'partner_id', 'product_name', 'product_code', 'product_uom', + 'min_qty', 'currency_id', 'date_start', 'date_end', + 'product_id', 'product_tmpl_id', 'delay' + ] + + for field_name in tracked_fields: + field = supplierinfo._fields.get(field_name) + self.assertTrue(field.tracking, f"Field {field_name} should have tracking enabled") + + def test_chatter_message_generation_on_write(self): + """Test that chatter messages are generated when supplierinfo is updated""" + # Create a supplierinfo record + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'product_id': self.product_variant.id if self.product_variant else False, + 'min_qty': 1.0, + 'price': 10.0, + }) + + # Clear any existing messages + if self.product_template: + self.product_template.message_ids.unlink() + if self.product_variant: + self.product_variant.message_ids.unlink() + + # Update the supplierinfo to trigger chatter + supplierinfo.write({ + 'price': 15.0, + 'min_qty': 2.0, + }) + + # Check that messages were posted to product template + if self.product_template: + template_messages = self.product_template.message_ids + self.assertTrue(len(template_messages) > 0, "Should have posted message to product template") + + # Check that messages were posted to product variant if it exists + if self.product_variant: + variant_messages = self.product_variant.message_ids + self.assertTrue(len(variant_messages) > 0, "Should have posted message to product variant") + + # Verify message content contains the changes + message_body = template_messages[0].body + self.assertIn('Price modify', message_body) + self.assertIn('min_qty', message_body) + + def test_chatter_message_content_structure(self): + """Test the structure and content of generated chatter messages""" + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'product_id': self.product_variant.id if self.product_variant else False, + 'min_qty': 5.0, + 'price': 75.0, + 'date_start': '2024-01-01', + 'date_end': '2024-12-31', + }) + + # Clear existing messages + if self.product_template: + self.product_template.message_ids.unlink() + if self.product_variant: + self.product_variant.message_ids.unlink() + + # Update to trigger chatter message + supplierinfo.write({'price': 80.0, 'min_qty': 10.0}) + + # Check that messages were created + if self.product_template: + template_messages = self.product_template.message_ids + self.assertTrue(len(template_messages) > 0, "Should have posted message to product template") + + # Verify message content structure + message_body = template_messages[0].body + self.assertIn('Price modify', message_body) + self.assertIn('price --> 80.0', message_body) + self.assertIn('min_qty --> 10.0', message_body) + + def test_chatter_message_without_variant(self): + """Test chatter message generation when no product variant is specified""" + # Create supplierinfo without variant + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'min_qty': 1.0, + 'price': 50.0, + }) + + # Clear existing messages + if self.product_template: + self.product_template.message_ids.unlink() + + # Update to trigger chatter message + supplierinfo.write({'price': 60.0}) + + # Verify message was posted to template + if self.product_template: + template_messages = self.product_template.message_ids + self.assertTrue(len(template_messages) > 0, "Should post message to template") + + # Verify message content + message_body = template_messages[0].body + self.assertIn('Price modify', message_body) + self.assertIn('price --> 60.0', message_body) + + def test_supplierinfo_show_details_action(self): + """Test the supplierinfo_show_details action method""" + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'product_id': self.product_variant.id, + 'min_qty': 1.0, + 'price': 25.0, + }) + + action = supplierinfo.supplierinfo_show_details() + + # Verify action structure + self.assertEqual(action['name'], 'Supplier price') + self.assertEqual(action['view_mode'], 'form') + self.assertEqual(action['res_model'], 'product.supplierinfo') + self.assertEqual(action['res_id'], supplierinfo.id) + self.assertEqual(action['type'], 'ir.actions.act_window') + + # Verify domain + expected_domain = [ + ('product_tmpl_id', '=', self.product_template.id), + ('product_id', '=', self.product_variant.id if self.product_variant else False), + ] + self.assertEqual(action['domain'], expected_domain) + + def test_partner_domain_constraint(self): + """Test that partner_id domain restricts to companies only""" + # Create a non-company partner + individual_partner = self.env['res.partner'].create({ + 'name': 'Individual Partner', + 'is_company': False, + }) + + # The domain constraint is applied at the view level, not model level + # So we test that the field has the correct domain definition + partner_field = self.env['product.supplierinfo']._fields['partner_id'] + self.assertEqual(partner_field.domain, [("is_company", "=", True)]) + + def test_multiple_supplierinfo_tracking(self): + """Test tracking with multiple supplierinfo records""" + supplierinfo1 = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'min_qty': 1.0, + 'price': 10.0, + }) + + supplier2 = self.env['res.partner'].create({ + 'name': 'Second Supplier', + 'is_company': True, + 'supplier_rank': 1, + }) + + supplierinfo2 = self.env['product.supplierinfo'].create({ + 'partner_id': supplier2.id, + 'product_tmpl_id': self.product_template.id, + 'min_qty': 5.0, + 'price': 8.0, + }) + + # Clear existing messages + self.product_template.message_ids.unlink() + + # Modify both + supplierinfo1.write({'price': 12.0}) + supplierinfo2.write({'price': 9.0}) + + # Should have messages for both modifications + messages = self.product_template.message_ids + self.assertEqual(len(messages), 2, "Should have messages for both supplierinfo modifications") + + def test_chatter_message_with_minimal_data(self): + """Test chatter message generation with minimal supplierinfo data""" + # Create minimal supplierinfo + supplierinfo = self.env['product.supplierinfo'].create({ + 'partner_id': self.partner_supplier.id, + 'product_tmpl_id': self.product_template.id, + 'price': 25.0, + }) + + # Clear existing messages + if self.product_template: + self.product_template.message_ids.unlink() + + # Update to trigger chatter message + supplierinfo.write({'price': 30.0}) + + # Verify basic message structure + if self.product_template: + template_messages = self.product_template.message_ids + self.assertTrue(len(template_messages) > 0, "Should have posted message") + + message_body = template_messages[0].body + self.assertIn('Price modify', message_body) + self.assertIn('price --> 30.0', message_body) + # Should not contain qty, dates since they weren't set + self.assertNotIn('Minimum qty', message_body) + self.assertNotIn('Starting', message_body) + self.assertNotIn('Ending', message_body) + + def test_inheritance_structure(self): + """Test that the model properly inherits required mixins""" + supplierinfo = self.env['product.supplierinfo'] + + # Check inheritance + self.assertIn('mail.thread', supplierinfo._inherit) + self.assertIn('mail.activity.mixin', supplierinfo._inherit) + self.assertIn('product.supplierinfo', supplierinfo._inherit) + + # Check that it's extending the existing model, not creating new one + self.assertEqual(supplierinfo._name, 'product.supplierinfo') diff --git a/product_supplierinfo_tracking/views/product_view.xml b/product_supplierinfo_tracking/views/product_view.xml index bc6787f..f68b8b2 100755 --- a/product_supplierinfo_tracking/views/product_view.xml +++ b/product_supplierinfo_tracking/views/product_view.xml @@ -1,13 +1,23 @@ - - product.supplierinfo.list.view2 - product.supplierinfo - + + + product.template.form.view.landed + + product.template - - 1 - + + + + {'default_product_tmpl_id': id, + 'product_template_invisible_variant': True, + 'list_view_ref':'product_supplierinfo_tracking.product_supplierinfo_tree_view_no_edit'} + + + + {'model': 'product.template', 'active_id': id, + 'list_view_ref':'product_supplierinfo_tracking.product_supplierinfo_tree_view_no_edit'} + - +
    \ No newline at end of file diff --git a/product_supplierinfo_tracking/views/supplierinfo.xml b/product_supplierinfo_tracking/views/supplierinfo.xml new file mode 100644 index 0000000..1881be4 --- /dev/null +++ b/product_supplierinfo_tracking/views/supplierinfo.xml @@ -0,0 +1,27 @@ + + + + + + product.supplierinfo.tree.no.edit + product.supplierinfo + + + + + + + + + + supplierinfo.pricelist.chatter + product.supplierinfo + + + + + + + + + \ No newline at end of file diff --git a/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml b/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml deleted file mode 100644 index 410d4de..0000000 --- a/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - supplierinfo.pricelist.chatter - product.supplierinfo - - - - - - - - - - - - - diff --git a/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml.backup b/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml.backup new file mode 100644 index 0000000..89ad638 --- /dev/null +++ b/product_supplierinfo_tracking/views/supplierinfo_pricelist.xml.backup @@ -0,0 +1,91 @@ + + + + + + supplierinfo.pricelist.chatter + product.supplierinfo + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +
    +
    +
    + + + + product.supplierinfo.company.groups + product.supplierinfo + + + + base.group_multi_company + + + + +
    + +
    \ No newline at end of file