From 77353635de6fca33e99a42bd8c4d28cab80a3c22 Mon Sep 17 00:00:00 2001 From: bosd Date: Tue, 20 May 2025 16:31:31 +0200 Subject: [PATCH 1/8] [ADD] stock_picking_partner_brand --- stock_picking_partner_brand/README.rst | 184 ++++++ stock_picking_partner_brand/__init__.py | 1 + stock_picking_partner_brand/__manifest__.py | 30 + .../models/__init__.py | 1 + .../models/stock_picking.py | 117 ++++ stock_picking_partner_brand/pyproject.toml | 3 + .../readme/CONFIGURE.md | 7 + stock_picking_partner_brand/readme/CONTEXT.md | 1 + .../readme/CONTRIBUTORS.md | 2 + stock_picking_partner_brand/readme/CREDITS.md | 4 + .../readme/DESCRIPTION.md | 3 + stock_picking_partner_brand/readme/HISTORY.md | 3 + stock_picking_partner_brand/readme/INSTALL.md | 7 + stock_picking_partner_brand/readme/ROADMAP.md | 1 + stock_picking_partner_brand/readme/USAGE.md | 23 + .../static/description/icon.png | Bin 0 -> 10254 bytes .../static/description/icon.svg | 1 + .../static/description/index.html | 523 ++++++++++++++++++ stock_picking_partner_brand/tests/__init__.py | 1 + .../tests/test_stock_picking_partner_brand.py | 293 ++++++++++ 20 files changed, 1205 insertions(+) create mode 100644 stock_picking_partner_brand/README.rst create mode 100644 stock_picking_partner_brand/__init__.py create mode 100644 stock_picking_partner_brand/__manifest__.py create mode 100644 stock_picking_partner_brand/models/__init__.py create mode 100644 stock_picking_partner_brand/models/stock_picking.py create mode 100644 stock_picking_partner_brand/pyproject.toml create mode 100644 stock_picking_partner_brand/readme/CONFIGURE.md create mode 100644 stock_picking_partner_brand/readme/CONTEXT.md create mode 100644 stock_picking_partner_brand/readme/CONTRIBUTORS.md create mode 100644 stock_picking_partner_brand/readme/CREDITS.md create mode 100644 stock_picking_partner_brand/readme/DESCRIPTION.md create mode 100644 stock_picking_partner_brand/readme/HISTORY.md create mode 100644 stock_picking_partner_brand/readme/INSTALL.md create mode 100644 stock_picking_partner_brand/readme/ROADMAP.md create mode 100644 stock_picking_partner_brand/readme/USAGE.md create mode 100644 stock_picking_partner_brand/static/description/icon.png create mode 100644 stock_picking_partner_brand/static/description/icon.svg create mode 100644 stock_picking_partner_brand/static/description/index.html create mode 100644 stock_picking_partner_brand/tests/__init__.py create mode 100644 stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py diff --git a/stock_picking_partner_brand/README.rst b/stock_picking_partner_brand/README.rst new file mode 100644 index 000000000..60e3ff63c --- /dev/null +++ b/stock_picking_partner_brand/README.rst @@ -0,0 +1,184 @@ +================================ +Stock Picking Partner Brand Sync +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:19c4ba24df7afee53062bd88c8b0d42d037f522c0bb9a6eea9d1167c06ddf4f8 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-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%2Fbrand-lightgray.png?logo=github + :target: https://github.com/OCA/brand/tree/18.0/stock_picking_partner_brand + :alt: OCA/brand +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/brand-18-0/brand-18-0-stock_picking_partner_brand + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/brand&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module is a glue module between ``sale_brand`` and +``partner_brand``. + +If the customer has a brand assigned, it will set that brand on the +Sales Order. If the customer has no brand, or if the customer is cleared +from the SO, the brand on the SO will also be cleared. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +This module was developed because it is a common use case for +(sub)contractors and other types of businesses to sell products under +different brands. + +Installation +============ + +To install this module, you need to: + +1. Place the ``sale_brand`` module in your Odoo addons path. +2. Install the ``partner_brand`` module in Odoo. + +It will auto install if all the dependencies are available. + +Configuration +============= + +1. Configure Brands on Partners: Navigate to Contacts. Open the customer + records for which you want to assign a brand. + +2. On the customer form, locate the "Brand" field (provided by + partner_brand) and select the appropriate brand. + +3. Save the changes. + +Usage +===== + +Automatic Brand Setting +----------------------- + +When you are on a Stock Picking form: + +Selecting a Customer with a Brand: + +If you select a customer in the "Customer" (partner_id) field, and that +customer has a brand assigned to them (via the brand_id field on their +contact record), the "Brand" field on the Stock picking will +automatically be populated with the customer's brand. + +Selecting a Customer without a Brand: + +If you select a customer who does not have a brand assigned to them, the +"Brand" field on the Stock Picking will be automatically cleared (set to +empty/None). + +*Changing Customer*: + +If you change the customer on an existing picking, the brand on the +picking will update according to the newly selected customer's brand (or +be cleared if the new customer has no brand). + +Clearing Customer: + +If you clear the "Customer" field on the stock picking (remove the +selected customer), the "Brand" field on the stock picking will also be +automatically cleared. + +This behavior is triggered by an onchange mechanism on the partner_id +field of the stock.picking model. + +*Manual Override* The automatic setting of the brand based on the +customer is a default behavior. After the brand is automatically +populated (or cleared), you can still manually change or set the brand +on the Stock Picking directly if needed. The onchange mechanism only +triggers when the partner_id field itself is modified. + +Known issues / Roadmap +====================== + + + +Changelog +========= + +18.0.1.0.0 (2025-05-20) +----------------------- + +- [ADD] First Release of module. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* O.B.S. Solutions + +Contributors +------------ + +- bosd + +Other credits +------------- + +The development of this module has been financially supported by: + +- OBS Solutions B.V. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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-bosd| image:: https://github.com/bosd.png?size=40px + :target: https://github.com/bosd + :alt: bosd + +Current `maintainer `__: + +|maintainer-bosd| + +This module is part of the `OCA/brand `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_picking_partner_brand/__init__.py b/stock_picking_partner_brand/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/stock_picking_partner_brand/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_picking_partner_brand/__manifest__.py b/stock_picking_partner_brand/__manifest__.py new file mode 100644 index 000000000..76de03fbd --- /dev/null +++ b/stock_picking_partner_brand/__manifest__.py @@ -0,0 +1,30 @@ +# Copyright 2025 OBS Solutions B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0) + +{ + "name": "Stock Picking Partner Brand Sync", + "summary": """ + Automatically sets the brand on a Stock Picking based on the + selected partner's brand. + """, + "version": "18.0.1.0.0", + "development_status": "Alpha", + "category": "Inventory", + "website": "https://github.com/OCA/brand", + "author": "O.B.S. Solutions, Odoo Community Association (OCA)", + "maintainers": ["bosd"], + "license": "AGPL-3", + "application": False, + "installable": True, + "auto_install": True, + "external_dependencies": { + "python": [], + "bin": [], + }, + "depends": [ + "stock", + "partner_brand", + "stock_brand", + ], + "data": [], +} diff --git a/stock_picking_partner_brand/models/__init__.py b/stock_picking_partner_brand/models/__init__.py new file mode 100644 index 000000000..ae4c27227 --- /dev/null +++ b/stock_picking_partner_brand/models/__init__.py @@ -0,0 +1 @@ +from . import stock_picking diff --git a/stock_picking_partner_brand/models/stock_picking.py b/stock_picking_partner_brand/models/stock_picking.py new file mode 100644 index 000000000..d9f344afe --- /dev/null +++ b/stock_picking_partner_brand/models/stock_picking.py @@ -0,0 +1,117 @@ +import logging + +from odoo import api, models + +_logger = logging.getLogger(__name__) + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + @api.onchange("partner_id") + def _onchange_partner_id_set_brand(self): + """ + Onchange method to set the brand_id on the Stock Picking + based on the selected partner's brand or its parent company's brand. + """ + brand_to_set = False + + if self.partner_id: + # Determine the partner whose brand should be checked + # Prefer the commercial entity (parent company) if it exists + partner_for_brand_check = ( + self.partner_id.commercial_partner_id or self.partner_id + ) # noqa + + if ( + hasattr(partner_for_brand_check, "brand_id") + and partner_for_brand_check.brand_id + ): # noqa + brand_to_set = partner_for_brand_check.brand_id + _logger.info( + f"Stock Picking (virtual ID " + "{self._origin.id if self._origin else 'New'}): " + f"Partner '{self.partner_id.name}' selected. " + f"Using brand from '{partner_for_brand_check.name}': " + "'{brand_to_set.name}' (ID: {brand_to_set.id})." + ) + else: + _logger.info( + f"Stock Picking (virtual ID " + "{self._origin.id if self._origin else 'New'}): " + f"Partner '{self.partner_id.name}' selected. " + f"Neither partner nor its commercial entity " + "'{partner_for_brand_check.name}' has a brand. Clearing brand." + ) + else: + _logger.info( + "Stock Picking (virtual ID " + "{self._origin.id if self._origin else 'New'}): " + "Partner cleared. Clearing brand." + ) + + # Set or clear the brand_id on the picking + if hasattr(self, "brand_id"): + self.brand_id = brand_to_set + else: + # This case should ideally not happen if stock_brand is correctly installed + if self.partner_id: + _logger.warning( + "Stock Picking model does not have a 'brand_id' field. " + "Is 'stock_brand' module installed and loaded correctly?" + ) + + @api.model_create_multi + def create(self, vals_list): + """ + Override create to ensure brand_id is set from partner_id + (or its commercial entity) + if provided during direct creation, and not already set in vals. + """ + for vals in vals_list: + # Only attempt to set brand_id if partner_id is provided and brand_id is not + # already in vals + if vals.get("partner_id") and "brand_id" not in vals: + partner = self.env["res.partner"].browse(vals.get("partner_id")) + if partner.exists(): + # Determine the partner whose brand should be checked + partner_for_brand_check = partner.commercial_partner_id or partner + + if ( + hasattr(partner_for_brand_check, "brand_id") + and partner_for_brand_check.brand_id + ): # noqa + # Check if the stock.picking model (self) has brand_id field + if "brand_id" in self._fields: + vals["brand_id"] = partner_for_brand_check.brand_id.id + _logger.info( + f"Create Stock Picking: Partner" + " '{partner.name}' provided. " + f"Using brand from '{partner_for_brand_check.name}': " + "'{partner_for_brand_check.brand_id.name}'. " + f"Setting brand_id in creation vals." + ) + else: + _logger.warning( + "Stock Picking model does not have a 'brand_id' " + "field during create. " + "Is 'stock_brand' module installed?" + ) + else: + _logger.info( + f"Create Stock Picking: Partner '{partner.name}' provided. " + f"Neither partner nor its commercial entity " + "'{partner_for_brand_check.name}' has a brand. " + f"brand_id not set from partner." + ) + + records = super().create(vals_list) + + # The onchange logic might also be triggered after creation if + # partner_id is set, + # but explicitly handling it here ensures it's + # set during the initial create call + # if possible. Re-triggering onchange or a direct write post-create is generally + # less efficient if it can be handled in the initial vals. + + return records diff --git a/stock_picking_partner_brand/pyproject.toml b/stock_picking_partner_brand/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/stock_picking_partner_brand/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/stock_picking_partner_brand/readme/CONFIGURE.md b/stock_picking_partner_brand/readme/CONFIGURE.md new file mode 100644 index 000000000..d3be9ccd1 --- /dev/null +++ b/stock_picking_partner_brand/readme/CONFIGURE.md @@ -0,0 +1,7 @@ +1. Configure Brands on Partners: +Navigate to Contacts. +Open the customer records for which you want to assign a brand. + +2. On the customer form, locate the "Brand" field (provided by partner_brand) and select the appropriate brand. + +3. Save the changes. diff --git a/stock_picking_partner_brand/readme/CONTEXT.md b/stock_picking_partner_brand/readme/CONTEXT.md new file mode 100644 index 000000000..447167025 --- /dev/null +++ b/stock_picking_partner_brand/readme/CONTEXT.md @@ -0,0 +1 @@ +This module was developed because it is a common use case for (sub)contractors and other types of businesses to sell products under different brands. diff --git a/stock_picking_partner_brand/readme/CONTRIBUTORS.md b/stock_picking_partner_brand/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..94d0e537e --- /dev/null +++ b/stock_picking_partner_brand/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ + +- bosd \ diff --git a/stock_picking_partner_brand/readme/CREDITS.md b/stock_picking_partner_brand/readme/CREDITS.md new file mode 100644 index 000000000..ded0986d1 --- /dev/null +++ b/stock_picking_partner_brand/readme/CREDITS.md @@ -0,0 +1,4 @@ + +The development of this module has been financially supported by: + +- OBS Solutions B.V. diff --git a/stock_picking_partner_brand/readme/DESCRIPTION.md b/stock_picking_partner_brand/readme/DESCRIPTION.md new file mode 100644 index 000000000..7e87ae55c --- /dev/null +++ b/stock_picking_partner_brand/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +This module is a glue module between `sale_brand` and `partner_brand`. + +If the customer has a brand assigned, it will set that brand on the Sales Order. If the customer has no brand, or if the customer is cleared from the SO, the brand on the SO will also be cleared. diff --git a/stock_picking_partner_brand/readme/HISTORY.md b/stock_picking_partner_brand/readme/HISTORY.md new file mode 100644 index 000000000..f2a3ae6af --- /dev/null +++ b/stock_picking_partner_brand/readme/HISTORY.md @@ -0,0 +1,3 @@ +## 18.0.1.0.0 (2025-05-20) + +- [ADD] First Release of module. diff --git a/stock_picking_partner_brand/readme/INSTALL.md b/stock_picking_partner_brand/readme/INSTALL.md new file mode 100644 index 000000000..d8a2a70f4 --- /dev/null +++ b/stock_picking_partner_brand/readme/INSTALL.md @@ -0,0 +1,7 @@ + +To install this module, you need to: + +1. Place the `sale_brand` module in your Odoo addons path. +2. Install the `partner_brand` module in Odoo. + +It will auto install if all the dependencies are available. diff --git a/stock_picking_partner_brand/readme/ROADMAP.md b/stock_picking_partner_brand/readme/ROADMAP.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/stock_picking_partner_brand/readme/ROADMAP.md @@ -0,0 +1 @@ + diff --git a/stock_picking_partner_brand/readme/USAGE.md b/stock_picking_partner_brand/readme/USAGE.md new file mode 100644 index 000000000..382a1692f --- /dev/null +++ b/stock_picking_partner_brand/readme/USAGE.md @@ -0,0 +1,23 @@ +## Automatic Brand Setting +When you are on a Stock Picking form: + +Selecting a Customer with a Brand: + +If you select a customer in the "Customer" (partner_id) field, and that customer has a brand assigned to them (via the brand_id field on their contact record), the "Brand" field on the Stock picking will automatically be populated with the customer's brand. + +Selecting a Customer without a Brand: + +If you select a customer who does not have a brand assigned to them, the "Brand" field on the Stock Picking will be automatically cleared (set to empty/None). + +*Changing Customer*: + +If you change the customer on an existing picking, the brand on the picking will update according to the newly selected customer's brand (or be cleared if the new customer has no brand). + +Clearing Customer: + +If you clear the "Customer" field on the stock picking (remove the selected customer), the "Brand" field on the stock picking will also be automatically cleared. + +This behavior is triggered by an onchange mechanism on the partner_id field of the stock.picking model. + +*Manual Override* +The automatic setting of the brand based on the customer is a default behavior. After the brand is automatically populated (or cleared), you can still manually change or set the brand on the Stock Picking directly if needed. The onchange mechanism only triggers when the partner_id field itself is modified. diff --git a/stock_picking_partner_brand/static/description/icon.png b/stock_picking_partner_brand/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 \ No newline at end of file diff --git a/stock_picking_partner_brand/static/description/index.html b/stock_picking_partner_brand/static/description/index.html new file mode 100644 index 000000000..93282f301 --- /dev/null +++ b/stock_picking_partner_brand/static/description/index.html @@ -0,0 +1,523 @@ + + + + + +Stock Picking Partner Brand Sync + + + +
+

Stock Picking Partner Brand Sync

+ + +

Alpha License: AGPL-3 OCA/brand Translate me on Weblate Try me on Runboat

+

This module is a glue module between sale_brand and +partner_brand.

+

If the customer has a brand assigned, it will set that brand on the +Sales Order. If the customer has no brand, or if the customer is cleared +from the SO, the brand on the SO will also be cleared.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Use Cases / Context

+

This module was developed because it is a common use case for +(sub)contractors and other types of businesses to sell products under +different brands.

+
+
+

Installation

+

To install this module, you need to:

+
    +
  1. Place the sale_brand module in your Odoo addons path.
  2. +
  3. Install the partner_brand module in Odoo.
  4. +
+

It will auto install if all the dependencies are available.

+
+
+

Configuration

+
    +
  1. Configure Brands on Partners: Navigate to Contacts. Open the customer +records for which you want to assign a brand.
  2. +
  3. On the customer form, locate the “Brand” field (provided by +partner_brand) and select the appropriate brand.
  4. +
  5. Save the changes.
  6. +
+
+
+

Usage

+
+

Automatic Brand Setting

+

When you are on a Stock Picking form:

+

Selecting a Customer with a Brand:

+

If you select a customer in the “Customer” (partner_id) field, and that +customer has a brand assigned to them (via the brand_id field on their +contact record), the “Brand” field on the Stock picking will +automatically be populated with the customer’s brand.

+

Selecting a Customer without a Brand:

+

If you select a customer who does not have a brand assigned to them, the +“Brand” field on the Stock Picking will be automatically cleared (set to +empty/None).

+

Changing Customer:

+

If you change the customer on an existing picking, the brand on the +picking will update according to the newly selected customer’s brand (or +be cleared if the new customer has no brand).

+

Clearing Customer:

+

If you clear the “Customer” field on the stock picking (remove the +selected customer), the “Brand” field on the stock picking will also be +automatically cleared.

+

This behavior is triggered by an onchange mechanism on the partner_id +field of the stock.picking model.

+

Manual Override The automatic setting of the brand based on the +customer is a default behavior. After the brand is automatically +populated (or cleared), you can still manually change or set the brand +on the Stock Picking directly if needed. The onchange mechanism only +triggers when the partner_id field itself is modified.

+
+
+ +
+

Changelog

+
+

18.0.1.0.0 (2025-05-20)

+
    +
  • [ADD] First Release of module.
  • +
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +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 +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • O.B.S. Solutions
  • +
+
+ +
+

Other credits

+

The development of this module has been financially supported by:

+
    +
  • OBS Solutions B.V.
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

Current maintainer:

+

bosd

+

This module is part of the OCA/brand project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/stock_picking_partner_brand/tests/__init__.py b/stock_picking_partner_brand/tests/__init__.py new file mode 100644 index 000000000..e7ecb708e --- /dev/null +++ b/stock_picking_partner_brand/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_picking_partner_brand diff --git a/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py new file mode 100644 index 000000000..32440bac9 --- /dev/null +++ b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py @@ -0,0 +1,293 @@ +import logging + +from odoo.tests import common, tagged + +_logger = logging.getLogger(__name__) + + +@tagged("post_install", "-at_install", "stock_picking_partner_brand") +class TestStockPickingPartnerBrand(common.TransactionCase): + """ + Test cases for the stock_picking_partner_brand module. + Verifies that the brand_id on a Stock Picking is correctly updated + when the partner_id changes, based on the partner's or commercial partner's + assigned brand. + """ + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + + # Models + cls.ResPartner = cls.env["res.partner"] + cls.ResBrand = cls.env["res.brand"] + cls.StockPicking = cls.env["stock.picking"] + cls.StockPickingType = cls.env["stock.picking.type"] + cls.ProductProduct = cls.env["product.product"] + + # Create Brands + cls.brand_alpha = cls.ResBrand.create({"name": "Test Brand Alpha"}) + cls.brand_beta = cls.ResBrand.create({"name": "Test Brand Beta"}) + + # Create Partners + cls.parent_company_with_brand_alpha = cls.ResPartner.create( + { + "name": "Parent Co Alpha", + "is_company": True, + "brand_id": cls.brand_alpha.id, + } + ) + cls.child_contact_of_alpha = cls.ResPartner.create( + { + "name": "Child Contact of Alpha", + "parent_id": cls.parent_company_with_brand_alpha.id, + "type": "contact", + # This child contact intentionally does not have its own brand_id + } + ) + cls.standalone_partner_with_brand_beta = cls.ResPartner.create( + { + "name": "Standalone Customer Beta", + "is_company": True, + "brand_id": cls.brand_beta.id, + } + ) + cls.partner_without_brand = cls.ResPartner.create( + { + "name": "Customer Without Any Brand", + "is_company": True, + } + ) + cls.child_contact_no_parent_brand = cls.ResPartner.create( + { + "name": "Child Contact, Parent No Brand", + "parent_id": cls.partner_without_brand.id, + "type": "contact", + } + ) + + cls.picking_type_out = cls.env["stock.picking.type"].search( + [ + ("code", "=", "outgoing"), + ("warehouse_id.company_id", "=", cls.env.company.id), + ], + limit=1, + ) + if not cls.picking_type_out: + warehouse = cls.env["stock.warehouse"].search( + [("company_id", "=", cls.env.company.id)], limit=1 + ) + if not warehouse: + warehouse = cls.env["stock.warehouse"].create( + { + "name": "Test Warehouse", + "code": "TSTWH", + "company_id": cls.env.company.id, + } + ) + cls.picking_type_out = cls.StockPickingType.create( + { + "name": "Test Pickings Out", + "code": "outgoing", + "warehouse_id": warehouse.id, + "sequence_code": "TSTOUT", + } + ) + + cls.product_generic = cls.ProductProduct.create( + {"name": "Generic Product", "type": "consu"} + ) + + _logger.info("TestStockPickingPartnerBrand: setUpClass completed.") + + def _create_picking_form(self, partner_id=None): + """ + Helper to simulate opening a new stock picking form with an optional partner. + """ + vals = {"picking_type_id": self.picking_type_out.id} + if partner_id: + vals["partner_id"] = partner_id + return self.StockPicking.new(vals) + + def test_01_onchange_child_contact_gets_parent_brand(self): + """Test brand is set from parent company when a child contact is selected.""" + _logger.info("Running test_01_onchange_child_contact_gets_parent_brand...") + + picking_form = self._create_picking_form( + partner_id=self.child_contact_of_alpha.id + ) + picking_form._onchange_partner_id_set_brand() + + self.assertTrue(picking_form.brand_id, "Brand should be set on the picking.") + self.assertEqual( + picking_form.brand_id, + self.parent_company_with_brand_alpha.brand_id, + "Picking brand should match the parent company's brand.", + ) + _logger.info("Test 01 Passed.") + + def test_02_onchange_standalone_partner_with_brand(self): + """Test brand is set from a standalone partner who has a brand.""" + _logger.info("Running test_02_onchange_standalone_partner_with_brand...") + + picking_form = self._create_picking_form( + partner_id=self.standalone_partner_with_brand_beta.id + ) + picking_form._onchange_partner_id_set_brand() + + self.assertTrue(picking_form.brand_id, "Brand should be set on the picking.") + self.assertEqual( + picking_form.brand_id, + self.standalone_partner_with_brand_beta.brand_id, + "Picking brand should match the standalone partner's brand.", + ) + _logger.info("Test 02 Passed.") + + def test_03_onchange_partner_without_brand_and_no_parent_brand(self): + """Test brand is cleared if partner and its parent (if any) have no brand.""" + _logger.info( + "Running test_03_onchange_partner_without_brand_and_no_" "parent_brand..." + ) + + # First, test with a standalone partner without a brand + picking_form_no_brand_standalone = self._create_picking_form( + partner_id=self.partner_without_brand.id + ) + picking_form_no_brand_standalone._onchange_partner_id_set_brand() + self.assertFalse( + picking_form_no_brand_standalone.brand_id, + "Brand should be cleared for standalone partner without brand.", + ) + + # Second, test with a child contact whose parent has no brand + picking_form_no_brand_child = self._create_picking_form( + partner_id=self.child_contact_no_parent_brand.id + ) + picking_form_no_brand_child._onchange_partner_id_set_brand() + self.assertFalse( + picking_form_no_brand_child.brand_id, + "Brand should be cleared for child contact whose parent has " "no brand.", + ) + _logger.info("Test 03 Passed.") + + def test_04_onchange_partner_cleared(self): + """Test brand is cleared when the partner is removed from the picking.""" + _logger.info("Running test_04_onchange_partner_cleared...") + + picking_form = self._create_picking_form( + partner_id=self.parent_company_with_brand_alpha.id + ) + picking_form._onchange_partner_id_set_brand() # Set initial brand + self.assertEqual(picking_form.brand_id, self.brand_alpha) + + # Clear the partner + picking_form.partner_id = False + picking_form._onchange_partner_id_set_brand() + + self.assertFalse( + picking_form.brand_id, "Brand should be cleared when " "partner is removed." + ) + _logger.info("Test 04 Passed.") + + def test_05_create_picking_with_child_partner_gets_parent_brand(self): + """Test brand is set from parent during direct creation with a child partner.""" + _logger.info( + "Running test_05_create_picking_with_child_partner_gets_" "parent_brand..." + ) + picking = self.StockPicking.create( + { + "partner_id": self.child_contact_of_alpha.id, + "picking_type_id": self.picking_type_out.id, + "location_id": self.picking_type_out.default_location_src_id.id, + "location_dest_id": self.picking_type_out.default_location_dest_id.id, + } + ) + self.assertTrue(picking.brand_id, "Brand should be set on picking creation.") + self.assertEqual( + picking.brand_id, + self.parent_company_with_brand_alpha.brand_id, + "Picking brand should match parent company's brand " "on creation.", + ) + _logger.info("Test 05 Passed.") + + def test_06_create_picking_with_standalone_partner_with_brand(self): + """Test brand is set during direct creation with a standalone partner having a " + "brand.""" + _logger.info( + "Running test_06_create_picking_with_standalone_" "partner_with_brand..." + ) + picking = self.StockPicking.create( + { + "partner_id": self.standalone_partner_with_brand_beta.id, + "picking_type_id": self.picking_type_out.id, + "location_id": self.picking_type_out.default_location_src_id.id, + "location_dest_id": self.picking_type_out.default_location_dest_id.id, + } + ) + self.assertTrue(picking.brand_id, "Brand should be set on picking creation.") + self.assertEqual( + picking.brand_id, + self.standalone_partner_with_brand_beta.brand_id, + "Picking brand should match standalone partner's brand on " "creation.", + ) + _logger.info("Test 06 Passed.") + + def test_07_create_picking_with_partner_without_brand(self): + """ + Test brand is not set during direct creation if partner (and parent) + has no brand. + """ + _logger.info("Running test_07_create_picking_with_partner_without_brand...") + picking = self.StockPicking.create( + { + "partner_id": self.partner_without_brand.id, + "picking_type_id": self.picking_type_out.id, + "location_id": self.picking_type_out.default_location_src_id.id, + "location_dest_id": self.picking_type_out.default_location_dest_id.id, + } + ) + self.assertFalse( + picking.brand_id, + "Brand should not be set if partner " "(and parent) has no brand.", + ) + _logger.info("Test 07 Passed.") + + def test_08_create_picking_with_explicit_brand_overrides_partner_brand(self): + """Test that an explicitly provided brand_id in create vals is respected.""" + _logger.info( + "Running test_08_create_picking_with_explicit_brand_overrides_" + "partner_brand..." + ) + picking = self.StockPicking.create( + { + "partner_id": self.parent_company_with_brand_alpha.id, + "brand_id": self.brand_beta.id, + "picking_type_id": self.picking_type_out.id, + "location_id": self.picking_type_out.default_location_src_id.id, + "location_dest_id": self.picking_type_out.default_location_dest_id.id, + } + ) + self.assertTrue(picking.brand_id, "Brand should be set.") + self.assertEqual( + picking.brand_id, + self.brand_beta, + "Explicitly provided brand_id in create vals should override " + "partner's brand.", + ) + _logger.info("Test 08 Passed.") + + def test_09_create_picking_without_partner(self): + """Test creating a picking without a partner_id.""" + _logger.info("Running test_09_create_picking_without_partner...") + picking = self.StockPicking.create( + { + "picking_type_id": self.picking_type_out.id, + "location_id": self.picking_type_out.default_location_src_id.id, + "location_dest_id": self.picking_type_out.default_location_dest_id.id, + } + ) + self.assertFalse( + picking.brand_id, "Brand should not be set if no partner " "is provided." + ) + _logger.info("Test 09 Passed.") From 8e23a5c3b2e3bf0c8ae37cb194c3dbbcf4067d6b Mon Sep 17 00:00:00 2001 From: oca-ci Date: Wed, 17 Sep 2025 13:44:09 +0000 Subject: [PATCH 2/8] [UPD] Update stock_picking_partner_brand.pot --- .../i18n/stock_picking_partner_brand.pot | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 stock_picking_partner_brand/i18n/stock_picking_partner_brand.pot diff --git a/stock_picking_partner_brand/i18n/stock_picking_partner_brand.pot b/stock_picking_partner_brand/i18n/stock_picking_partner_brand.pot new file mode 100644 index 000000000..33b073547 --- /dev/null +++ b/stock_picking_partner_brand/i18n/stock_picking_partner_brand.pot @@ -0,0 +1,19 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_partner_brand +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_picking_partner_brand +#: model:ir.model,name:stock_picking_partner_brand.model_stock_picking +msgid "Transfer" +msgstr "" From ddcb10ffc7751aa8c4b11e007c514a581340975b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 17 Sep 2025 13:47:29 +0000 Subject: [PATCH 3/8] [BOT] post-merge updates --- stock_picking_partner_brand/README.rst | 14 +++--- .../static/description/index.html | 44 +++++++++++-------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/stock_picking_partner_brand/README.rst b/stock_picking_partner_brand/README.rst index 60e3ff63c..7a7ef07c2 100644 --- a/stock_picking_partner_brand/README.rst +++ b/stock_picking_partner_brand/README.rst @@ -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 + ================================ Stock Picking Partner Brand Sync ================================ @@ -7,13 +11,13 @@ Stock Picking Partner Brand Sync !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:19c4ba24df7afee53062bd88c8b0d42d037f522c0bb9a6eea9d1167c06ddf4f8 + !! source digest: sha256:21d109d64c9a3f8ac534b11caa8c03e70210a7617ec997d55d51c69b7b024887 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png :target: https://odoo-community.org/page/development-status :alt: Alpha -.. |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%2Fbrand-lightgray.png?logo=github @@ -126,7 +130,7 @@ Changelog 18.0.1.0.0 (2025-05-20) ----------------------- -- [ADD] First Release of module. +- [ADD] First Release of module. Bug Tracker =========== @@ -149,14 +153,14 @@ Authors Contributors ------------ -- bosd +- bosd Other credits ------------- The development of this module has been financially supported by: -- OBS Solutions B.V. +- OBS Solutions B.V. Maintainers ----------- diff --git a/stock_picking_partner_brand/static/description/index.html b/stock_picking_partner_brand/static/description/index.html index 93282f301..b06b71e2f 100644 --- a/stock_picking_partner_brand/static/description/index.html +++ b/stock_picking_partner_brand/static/description/index.html @@ -3,7 +3,7 @@ -Stock Picking Partner Brand Sync +README.rst -
-

Stock Picking Partner Brand Sync

+
+ + +Odoo Community Association + +
+

Stock Picking Partner Brand Sync

-

Alpha License: AGPL-3 OCA/brand Translate me on Weblate Try me on Runboat

+

Alpha License: AGPL-3 OCA/brand Translate me on Weblate Try me on Runboat

This module is a glue module between sale_brand and partner_brand.

If the customer has a brand assigned, it will set that brand on the @@ -407,13 +412,13 @@

Stock Picking Partner Brand Sync

-

Use Cases / Context

+

Use Cases / Context

This module was developed because it is a common use case for (sub)contractors and other types of businesses to sell products under different brands.

-

Installation

+

Installation

To install this module, you need to:

  1. Place the sale_brand module in your Odoo addons path.
  2. @@ -422,7 +427,7 @@

    Installation

    It will auto install if all the dependencies are available.

-

Configuration

+

Configuration

  1. Configure Brands on Partners: Navigate to Contacts. Open the customer records for which you want to assign a brand.
  2. @@ -432,9 +437,9 @@

    Configuration

-

Usage

+

Usage

-

Automatic Brand Setting

+

Automatic Brand Setting

When you are on a Stock Picking form:

Selecting a Customer with a Brand:

If you select a customer in the “Customer” (partner_id) field, and that @@ -463,19 +468,19 @@

Automatic Brand Setting

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. 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 @@ -483,28 +488,28 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • O.B.S. Solutions
-

Other credits

+

Other credits

The development of this module has been financially supported by:

  • OBS Solutions B.V.
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -519,5 +524,6 @@

Maintainers

+
From d4340ba59773305199d570df3f6e9e74048c2fc8 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 26 Sep 2025 16:34:53 +0000 Subject: [PATCH 4/8] Added translation using Weblate (Italian) --- stock_picking_partner_brand/i18n/it.po | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 stock_picking_partner_brand/i18n/it.po diff --git a/stock_picking_partner_brand/i18n/it.po b/stock_picking_partner_brand/i18n/it.po new file mode 100644 index 000000000..1aa37b6d7 --- /dev/null +++ b/stock_picking_partner_brand/i18n/it.po @@ -0,0 +1,20 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_picking_partner_brand +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: stock_picking_partner_brand +#: model:ir.model,name:stock_picking_partner_brand.model_stock_picking +msgid "Transfer" +msgstr "" From 512e558dd54285e22c74d63c2064e23e1ddcaa33 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 26 Sep 2025 16:35:08 +0000 Subject: [PATCH 5/8] Translated using Weblate (Italian) Currently translated at 100.0% (1 of 1 strings) Translation: brand-18.0/brand-18.0-stock_picking_partner_brand Translate-URL: https://translation.odoo-community.org/projects/brand-18-0/brand-18-0-stock_picking_partner_brand/it/ --- stock_picking_partner_brand/i18n/it.po | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stock_picking_partner_brand/i18n/it.po b/stock_picking_partner_brand/i18n/it.po index 1aa37b6d7..d512c2de9 100644 --- a/stock_picking_partner_brand/i18n/it.po +++ b/stock_picking_partner_brand/i18n/it.po @@ -6,15 +6,17 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2025-09-26 18:43+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" #. module: stock_picking_partner_brand #: model:ir.model,name:stock_picking_partner_brand.model_stock_picking msgid "Transfer" -msgstr "" +msgstr "Trasferimento" From 6a0e60e3063190296f84709b773ed0d8ab5a37ed Mon Sep 17 00:00:00 2001 From: Bhavesh Heliconia Date: Tue, 19 May 2026 17:32:53 +0530 Subject: [PATCH 6/8] [IMP] stock_picking_partner_brand: pre-commit auto fixes --- .../tests/test_stock_picking_partner_brand.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py index 32440bac9..161539770 100644 --- a/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py +++ b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py @@ -147,7 +147,7 @@ def test_02_onchange_standalone_partner_with_brand(self): def test_03_onchange_partner_without_brand_and_no_parent_brand(self): """Test brand is cleared if partner and its parent (if any) have no brand.""" _logger.info( - "Running test_03_onchange_partner_without_brand_and_no_" "parent_brand..." + "Running test_03_onchange_partner_without_brand_and_no_parent_brand..." ) # First, test with a standalone partner without a brand @@ -167,7 +167,7 @@ def test_03_onchange_partner_without_brand_and_no_parent_brand(self): picking_form_no_brand_child._onchange_partner_id_set_brand() self.assertFalse( picking_form_no_brand_child.brand_id, - "Brand should be cleared for child contact whose parent has " "no brand.", + "Brand should be cleared for child contact whose parent has no brand.", ) _logger.info("Test 03 Passed.") @@ -186,14 +186,14 @@ def test_04_onchange_partner_cleared(self): picking_form._onchange_partner_id_set_brand() self.assertFalse( - picking_form.brand_id, "Brand should be cleared when " "partner is removed." + picking_form.brand_id, "Brand should be cleared when partner is removed." ) _logger.info("Test 04 Passed.") def test_05_create_picking_with_child_partner_gets_parent_brand(self): """Test brand is set from parent during direct creation with a child partner.""" _logger.info( - "Running test_05_create_picking_with_child_partner_gets_" "parent_brand..." + "Running test_05_create_picking_with_child_partner_gets_parent_brand..." ) picking = self.StockPicking.create( { @@ -207,7 +207,7 @@ def test_05_create_picking_with_child_partner_gets_parent_brand(self): self.assertEqual( picking.brand_id, self.parent_company_with_brand_alpha.brand_id, - "Picking brand should match parent company's brand " "on creation.", + "Picking brand should match parent company's brand on creation.", ) _logger.info("Test 05 Passed.") @@ -215,7 +215,7 @@ def test_06_create_picking_with_standalone_partner_with_brand(self): """Test brand is set during direct creation with a standalone partner having a " "brand.""" _logger.info( - "Running test_06_create_picking_with_standalone_" "partner_with_brand..." + "Running test_06_create_picking_with_standalone_partner_with_brand..." ) picking = self.StockPicking.create( { @@ -229,7 +229,7 @@ def test_06_create_picking_with_standalone_partner_with_brand(self): self.assertEqual( picking.brand_id, self.standalone_partner_with_brand_beta.brand_id, - "Picking brand should match standalone partner's brand on " "creation.", + "Picking brand should match standalone partner's brand on creation.", ) _logger.info("Test 06 Passed.") @@ -249,7 +249,7 @@ def test_07_create_picking_with_partner_without_brand(self): ) self.assertFalse( picking.brand_id, - "Brand should not be set if partner " "(and parent) has no brand.", + "Brand should not be set if partner (and parent) has no brand.", ) _logger.info("Test 07 Passed.") @@ -288,6 +288,6 @@ def test_09_create_picking_without_partner(self): } ) self.assertFalse( - picking.brand_id, "Brand should not be set if no partner " "is provided." + picking.brand_id, "Brand should not be set if no partner is provided." ) _logger.info("Test 09 Passed.") From 957b5788edeab4c816841175872b498254fd088e Mon Sep 17 00:00:00 2001 From: Bhavesh Heliconia Date: Tue, 19 May 2026 17:34:24 +0530 Subject: [PATCH 7/8] [MIG] stock_picking_partner_brand: Migration to 19.0 --- stock_picking_partner_brand/README.rst | 13 +++--- stock_picking_partner_brand/__manifest__.py | 2 +- .../readme/CONTRIBUTORS.md | 2 + .../static/description/index.html | 10 +++-- .../tests/test_stock_picking_partner_brand.py | 43 ++----------------- 5 files changed, 21 insertions(+), 49 deletions(-) diff --git a/stock_picking_partner_brand/README.rst b/stock_picking_partner_brand/README.rst index 7a7ef07c2..3cb25da77 100644 --- a/stock_picking_partner_brand/README.rst +++ b/stock_picking_partner_brand/README.rst @@ -21,13 +21,13 @@ Stock Picking Partner Brand Sync :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fbrand-lightgray.png?logo=github - :target: https://github.com/OCA/brand/tree/18.0/stock_picking_partner_brand + :target: https://github.com/OCA/brand/tree/19.0/stock_picking_partner_brand :alt: OCA/brand .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/brand-18-0/brand-18-0-stock_picking_partner_brand + :target: https://translation.odoo-community.org/projects/brand-19-0/brand-19-0-stock_picking_partner_brand :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/brand&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/brand&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -138,7 +138,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -154,6 +154,9 @@ Contributors ------------ - bosd +- `Heliconia Solutions Pvt. Ltd. `__ + + - Bhavesh Heliconia Other credits ------------- @@ -183,6 +186,6 @@ Current `maintainer `__: |maintainer-bosd| -This module is part of the `OCA/brand `_ project on GitHub. +This module is part of the `OCA/brand `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_picking_partner_brand/__manifest__.py b/stock_picking_partner_brand/__manifest__.py index 76de03fbd..d47eb09a7 100644 --- a/stock_picking_partner_brand/__manifest__.py +++ b/stock_picking_partner_brand/__manifest__.py @@ -7,7 +7,7 @@ Automatically sets the brand on a Stock Picking based on the selected partner's brand. """, - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "development_status": "Alpha", "category": "Inventory", "website": "https://github.com/OCA/brand", diff --git a/stock_picking_partner_brand/readme/CONTRIBUTORS.md b/stock_picking_partner_brand/readme/CONTRIBUTORS.md index 94d0e537e..29e910277 100644 --- a/stock_picking_partner_brand/readme/CONTRIBUTORS.md +++ b/stock_picking_partner_brand/readme/CONTRIBUTORS.md @@ -1,2 +1,4 @@ - bosd \ +- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io) + - Bhavesh Heliconia diff --git a/stock_picking_partner_brand/static/description/index.html b/stock_picking_partner_brand/static/description/index.html index b06b71e2f..f98ab32a9 100644 --- a/stock_picking_partner_brand/static/description/index.html +++ b/stock_picking_partner_brand/static/description/index.html @@ -374,7 +374,7 @@

Stock Picking Partner Brand Sync

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:21d109d64c9a3f8ac534b11caa8c03e70210a7617ec997d55d51c69b7b024887 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Alpha License: AGPL-3 OCA/brand Translate me on Weblate Try me on Runboat

+

Alpha License: AGPL-3 OCA/brand Translate me on Weblate Try me on Runboat

This module is a glue module between sale_brand and partner_brand.

If the customer has a brand assigned, it will set that brand on the @@ -484,7 +484,7 @@

Bug Tracker

Bugs are tracked on GitHub Issues. 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 -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -519,7 +523,7 @@

Maintainers

promote its widespread use.

Current maintainer:

bosd

-

This module is part of the OCA/brand project on GitHub.

+

This module is part of the OCA/brand project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py index 161539770..01364283e 100644 --- a/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py +++ b/stock_picking_partner_brand/tests/test_stock_picking_partner_brand.py @@ -1,12 +1,10 @@ -import logging +from odoo.tests import tagged -from odoo.tests import common, tagged - -_logger = logging.getLogger(__name__) +from odoo.addons.base.tests.common import BaseCommon @tagged("post_install", "-at_install", "stock_picking_partner_brand") -class TestStockPickingPartnerBrand(common.TransactionCase): +class TestStockPickingPartnerBrand(BaseCommon): """ Test cases for the stock_picking_partner_brand module. Verifies that the brand_id on a Stock Picking is correctly updated @@ -17,8 +15,6 @@ class TestStockPickingPartnerBrand(common.TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - # Models cls.ResPartner = cls.env["res.partner"] cls.ResBrand = cls.env["res.brand"] @@ -99,8 +95,6 @@ def setUpClass(cls): {"name": "Generic Product", "type": "consu"} ) - _logger.info("TestStockPickingPartnerBrand: setUpClass completed.") - def _create_picking_form(self, partner_id=None): """ Helper to simulate opening a new stock picking form with an optional partner. @@ -112,8 +106,6 @@ def _create_picking_form(self, partner_id=None): def test_01_onchange_child_contact_gets_parent_brand(self): """Test brand is set from parent company when a child contact is selected.""" - _logger.info("Running test_01_onchange_child_contact_gets_parent_brand...") - picking_form = self._create_picking_form( partner_id=self.child_contact_of_alpha.id ) @@ -125,12 +117,9 @@ def test_01_onchange_child_contact_gets_parent_brand(self): self.parent_company_with_brand_alpha.brand_id, "Picking brand should match the parent company's brand.", ) - _logger.info("Test 01 Passed.") def test_02_onchange_standalone_partner_with_brand(self): """Test brand is set from a standalone partner who has a brand.""" - _logger.info("Running test_02_onchange_standalone_partner_with_brand...") - picking_form = self._create_picking_form( partner_id=self.standalone_partner_with_brand_beta.id ) @@ -142,14 +131,9 @@ def test_02_onchange_standalone_partner_with_brand(self): self.standalone_partner_with_brand_beta.brand_id, "Picking brand should match the standalone partner's brand.", ) - _logger.info("Test 02 Passed.") def test_03_onchange_partner_without_brand_and_no_parent_brand(self): """Test brand is cleared if partner and its parent (if any) have no brand.""" - _logger.info( - "Running test_03_onchange_partner_without_brand_and_no_parent_brand..." - ) - # First, test with a standalone partner without a brand picking_form_no_brand_standalone = self._create_picking_form( partner_id=self.partner_without_brand.id @@ -169,12 +153,9 @@ def test_03_onchange_partner_without_brand_and_no_parent_brand(self): picking_form_no_brand_child.brand_id, "Brand should be cleared for child contact whose parent has no brand.", ) - _logger.info("Test 03 Passed.") def test_04_onchange_partner_cleared(self): """Test brand is cleared when the partner is removed from the picking.""" - _logger.info("Running test_04_onchange_partner_cleared...") - picking_form = self._create_picking_form( partner_id=self.parent_company_with_brand_alpha.id ) @@ -188,13 +169,9 @@ def test_04_onchange_partner_cleared(self): self.assertFalse( picking_form.brand_id, "Brand should be cleared when partner is removed." ) - _logger.info("Test 04 Passed.") def test_05_create_picking_with_child_partner_gets_parent_brand(self): """Test brand is set from parent during direct creation with a child partner.""" - _logger.info( - "Running test_05_create_picking_with_child_partner_gets_parent_brand..." - ) picking = self.StockPicking.create( { "partner_id": self.child_contact_of_alpha.id, @@ -209,14 +186,10 @@ def test_05_create_picking_with_child_partner_gets_parent_brand(self): self.parent_company_with_brand_alpha.brand_id, "Picking brand should match parent company's brand on creation.", ) - _logger.info("Test 05 Passed.") def test_06_create_picking_with_standalone_partner_with_brand(self): """Test brand is set during direct creation with a standalone partner having a " "brand.""" - _logger.info( - "Running test_06_create_picking_with_standalone_partner_with_brand..." - ) picking = self.StockPicking.create( { "partner_id": self.standalone_partner_with_brand_beta.id, @@ -231,14 +204,12 @@ def test_06_create_picking_with_standalone_partner_with_brand(self): self.standalone_partner_with_brand_beta.brand_id, "Picking brand should match standalone partner's brand on creation.", ) - _logger.info("Test 06 Passed.") def test_07_create_picking_with_partner_without_brand(self): """ Test brand is not set during direct creation if partner (and parent) has no brand. """ - _logger.info("Running test_07_create_picking_with_partner_without_brand...") picking = self.StockPicking.create( { "partner_id": self.partner_without_brand.id, @@ -251,14 +222,9 @@ def test_07_create_picking_with_partner_without_brand(self): picking.brand_id, "Brand should not be set if partner (and parent) has no brand.", ) - _logger.info("Test 07 Passed.") def test_08_create_picking_with_explicit_brand_overrides_partner_brand(self): """Test that an explicitly provided brand_id in create vals is respected.""" - _logger.info( - "Running test_08_create_picking_with_explicit_brand_overrides_" - "partner_brand..." - ) picking = self.StockPicking.create( { "partner_id": self.parent_company_with_brand_alpha.id, @@ -275,11 +241,9 @@ def test_08_create_picking_with_explicit_brand_overrides_partner_brand(self): "Explicitly provided brand_id in create vals should override " "partner's brand.", ) - _logger.info("Test 08 Passed.") def test_09_create_picking_without_partner(self): """Test creating a picking without a partner_id.""" - _logger.info("Running test_09_create_picking_without_partner...") picking = self.StockPicking.create( { "picking_type_id": self.picking_type_out.id, @@ -290,4 +254,3 @@ def test_09_create_picking_without_partner(self): self.assertFalse( picking.brand_id, "Brand should not be set if no partner is provided." ) - _logger.info("Test 09 Passed.") From f6a73af03dd5cf3990e316815256a4a2ab0fc998 Mon Sep 17 00:00:00 2001 From: Bhavesh Heliconia Date: Tue, 19 May 2026 17:36:10 +0530 Subject: [PATCH 8/8] [DON'T MERGE] test-requirements.txt --- test-requirements.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test-requirements.txt diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..ad5002c49 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,4 @@ +odoo-addon-partner_brand @ git+https://github.com/OCA/brand.git@refs/pull/302/head#subdirectory=partner_brand +odoo-addon-account_brand @ git+https://github.com/OCA/brand.git@refs/pull/303/head#subdirectory=account_brand +odoo-addon-sale_brand @ git+https://github.com/OCA/brand.git@refs/pull/305/head#subdirectory=sale_brand +odoo-addon-stock_brand @ git+https://github.com/OCA/brand.git@refs/pull/308/head#subdirectory=stock_brand