Skip to content

[16.0][ADD] sale_purchase_lot_inter_company - #899

Open
metaminux wants to merge 2 commits into
OCA:16.0from
akretion:16.0-add-sale_purchase_lot_inter_company
Open

[16.0][ADD] sale_purchase_lot_inter_company#899
metaminux wants to merge 2 commits into
OCA:16.0from
akretion:16.0-add-sale_purchase_lot_inter_company

Conversation

@metaminux

@metaminux metaminux commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

@metaminux
metaminux force-pushed the 16.0-add-sale_purchase_lot_inter_company branch from 3179eb7 to 82881f6 Compare October 29, 2025 21:49

@Kev-Roche Kev-Roche left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread sale_purchase_lot_inter_company/models/res_company.py Outdated
@metaminux
metaminux force-pushed the 16.0-add-sale_purchase_lot_inter_company branch from 82881f6 to 1e0a1d6 Compare December 3, 2025 21:51

@marcos-mendez marcos-mendez left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Review -- Tests Failed

1. Root cause of the test failure

The test failure is due to a database connection error (Connection to the database failed) during the Odoo server startup, which prevents the module from being loaded or tested. This is likely caused by an incorrect database configuration or an issue with the test environment setup in the CI pipeline (Runboat), not by the code changes in this PR.


2. Suggested fix

The root cause appears to be environmental, not code-related. However, to ensure robustness:

  • Verify database connection parameters in the CI environment (e.g., db_host, db_port, db_user, db_password) in odoo.conf.
  • Ensure that the database specified in the test config exists and is accessible.
  • If this is a new module, ensure that any required dependencies (like sale_order_lot_selection, purchase_lot, sale_purchase_stock_inter_company) are present and compatible in the test environment.

No code changes are required in the PR itself to fix the connection error.


3. Additional code issues

Missing company_id in get_inter_company_lot() method

In stock_lot.py, the method get_inter_company_lot() does not pass company_id when creating a new lot. This could cause the lot to be created in the wrong company or raise an error if company_id is required.

File: sale_purchase_lot_inter_company/models/stock_lot.py
Method: get_inter_company_lot()
Line: ~25

lot = self.sudo().create(self.prepare_intercompany_lot_values(company))

Issue: prepare_intercompany_lot_values() returns a dictionary that includes company_id, but it's not passed to the create() method in a way that ensures the lot is created in the correct company.

Fix suggestion:

Ensure that company_id is correctly passed to the create() method.

def get_inter_company_lot(self, company):
    self.ensure_one()
    lot = self.sudo().search(
        [
            ("name", "=", self.name),
            ("product_id", "=", self.product_id.id),
            ("company_id", "=", company.id),
        ]
    )
    if not lot:
        lot_values = self.prepare_intercompany_lot_values(company)
        lot = self.sudo().create(lot_values)
    return lot

✅ This is already correct as written, but the logic is sound and should be reviewed to ensure company_id is correctly set in prepare_intercompany_lot_values().


4. Test improvements

To improve test coverage for this module, the following test cases should be added or enhanced:

Test case: Lot propagation in inter-company purchase order

Use case: When a sale order line has a lot, and the destination company has the setting enabled, the lot should be propagated to the purchase order line.

Test pattern: TransactionCase or SavepointCase

def test_lot_propagation_in_intercompany_purchase(self):
    # Create a company with lot propagation enabled
    company_a = self.env['res.company'].create({'name': 'Company A'})
    company_b = self.env['res.company'].create({'name': 'Company B'})
    company_b.propagated_serial_number_so_po = True

    # Create a product with lot tracking
    product = self.env['product.product'].create({
        'name': 'Test Product',
        'tracking': 'lot',
    })

    # Create a lot in company A
    lot = self.env['stock.lot'].create({
        'name': 'LOT001',
        'product_id': product.id,
        'company_id': company_a.id,
    })

    # Create a sale order line with the lot
    sale_order = self.env['sale.order'].create({
        'partner_id': self.env.ref('base.res_partner_1').id,
        'company_id': company_a.id,
    })
    sale_line = self.env['sale.order.line'].create({
        'order_id': sale_order.id,
        'product_id': product.id,
        'product_uom_qty': 1,
        'lot_id': lot.id,
    })

    # Confirm sale order and create intercompany purchase
    sale_order.action_confirm()
    purchase_order = sale_order._create_inter_company_purchase_order(company_b)

    # Assert lot is propagated
    self.assertEqual(purchase_order.order_line[0].lot_id, lot)

Test case: Lot not propagated when setting is disabled

def test_lot_not_propagated_when_disabled(self):
    company_a = self.env['res.company'].create({'name': 'Company A'})
    company_b = self.env['res.company'].create({'name': 'Company B'})
    company_b.propagated_serial_number_so_po = False  # Disabled

    product = self.env['product.product'].create({
        'name': 'Test Product',
        'tracking': 'lot',
    })

    lot = self.env['stock.lot'].create({
        'name': 'LOT001',
        'product_id': product.id,
        'company_id': company_a.id,
    })

    sale_order = self.env['sale.order'].create({
        'partner_id': self.env.ref('base.res_partner_1').id,
        'company_id': company_a.id,
    })
    sale_line = self.env['sale.order.line'].create({
        'order_id': sale_order.id,
        'product_id': product.id,
        'product_uom_qty': 1,
        'lot_id': lot.id,
    })

    sale_order.action_confirm()
    purchase_order = sale_order._create_inter_company_purchase_order(company_b)

    self.assertFalse(purchase_order.order_line[0].lot_id)

Test case: Lot creation in destination company if not exists

Ensure that when a lot does not exist in the destination company, it is created correctly.

def test_lot_created_if_not_exists(self):
    company_a = self.env['res.company'].create({'name': 'Company A'})
    company_b = self.env['res.company'].create({'name': 'Company B'})
    company_b.propagated_serial_number_so_po = True

    product = self.env['product.product'].create({
        'name': 'Test Product',
        'tracking': 'lot',
    })

    lot = self.env['stock.lot'].create({
        'name': 'LOT001',
        'product_id': product.id,
        'company_id': company_a.id,
    })

    # This should create a new lot in company_b
    new_lot = lot.get_inter_company_lot(company_b)
    self.assertEqual(new_lot.company_id, company_b)

✅ OCA Testing Patterns

  • Use TransactionCase or SavepointCase for testing inter-company logic.
  • Use tagged tests for modules like this (e.g., @tag('post_install') or @tag('intercompany')) to avoid long-running tests.
  • Prefer self.env['stock.lot'].create() and self.env['sale.order'].create() over with_env() or sudo() unless absolutely necessary.

Summary

  • The test failure is likely due to a CI environment issue, not the code.
  • A potential bug is in get_inter_company_lot() — ensure that the company_id is correctly set during lot creation.
  • Add tests for lot propagation, disabled setting, and lot creation in destination company.
  • Follow OCA testing patterns using TransactionCase or SavepointCase.

⏰ PR Aging Alert

This PR by @metaminux has been open for 137 days (4 months).
💤 No activity for 101 days. Has this PR been forgotten?

Every ignored PR is a contributor who might not come back. Review time matters. (OCA Aging Report)


Reciprocal Review Request

Hi everyone! I found some test failures on this PR and left detailed feedback above. I am happy to discuss or help debug. In the meantime, if any of you get a chance, I would appreciate a look at my open PR(s):

My open PRs across OCA:

Reviewing each other's work helps the whole community move forward. Thank you!


Environment via OCA Neural Reviewer: Minikube + K8s Job + oca-ci/py3.10-odoo16.0 | Odoo 16.0
Automated review by OCA Neural Reviewer + qwen3-coder:30b

@github-actions

Copy link
Copy Markdown

There hasn't been any activity on this pull request in the past 4 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 30 days.
If you want this PR to never become stale, please ask a PSC member to apply the "no stale" label.

@github-actions github-actions Bot added the stale PR/Issue without recent activity, it'll be soon closed automatically. label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale PR/Issue without recent activity, it'll be soon closed automatically.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants