79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
|
|
import logging
|
|
from odoo import models, fields, api
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FusionWarehouseInventory(models.Model):
|
|
_name = 'fusion.warehouse.inventory'
|
|
_description = 'Shared Warehouse Inventory Ownership'
|
|
_rec_name = 'display_name'
|
|
_order = 'product_id, owner_config_id'
|
|
|
|
product_id = fields.Many2one(
|
|
'product.product', string='Product',
|
|
required=True, ondelete='cascade', index=True)
|
|
product_tmpl_id = fields.Many2one(
|
|
related='product_id.product_tmpl_id', store=True)
|
|
lot_id = fields.Many2one(
|
|
'stock.lot', string='Serial/Lot',
|
|
help='Serial number or lot for tracked products')
|
|
owner_config_id = fields.Many2one(
|
|
'fusion.sync.config', string='Owner Instance',
|
|
required=True, ondelete='restrict',
|
|
help='The Odoo instance that owns this inventory')
|
|
quantity = fields.Float(string='Quantity', default=1.0)
|
|
location_bin = fields.Char(
|
|
string='Bin / Shelf',
|
|
help='Physical location within the shared warehouse')
|
|
warehouse_location_id = fields.Many2one(
|
|
'stock.location', string='Warehouse Location',
|
|
related='owner_config_id.warehouse_location_id', store=True)
|
|
state = fields.Selection([
|
|
('available', 'Available'),
|
|
('reserved', 'Reserved'),
|
|
('in_transit', 'In Transit'),
|
|
('transferred', 'Transferred'),
|
|
], string='Status', default='available', required=True, index=True)
|
|
notes = fields.Text(string='Notes')
|
|
|
|
display_name = fields.Char(compute='_compute_display_name')
|
|
|
|
@api.depends('product_id', 'owner_config_id', 'quantity')
|
|
def _compute_display_name(self):
|
|
for rec in self:
|
|
owner = rec.owner_config_id.name or 'Unknown'
|
|
rec.display_name = f'{rec.product_id.name} ({rec.quantity} - {owner})'
|
|
|
|
@api.model
|
|
def get_available_for_product(self, product_id, exclude_owner_id=None):
|
|
"""Get available warehouse inventory for a product, optionally excluding an owner."""
|
|
domain = [
|
|
('product_id', '=', product_id),
|
|
('state', '=', 'available'),
|
|
('quantity', '>', 0),
|
|
]
|
|
if exclude_owner_id:
|
|
domain.append(('owner_config_id', '!=', exclude_owner_id))
|
|
return self.search(domain)
|
|
|
|
def action_reserve(self):
|
|
for rec in self.filtered(lambda r: r.state == 'available'):
|
|
rec.state = 'reserved'
|
|
|
|
def action_mark_in_transit(self):
|
|
for rec in self.filtered(lambda r: r.state in ('available', 'reserved')):
|
|
rec.state = 'in_transit'
|
|
|
|
def action_mark_transferred(self):
|
|
for rec in self.filtered(lambda r: r.state == 'in_transit'):
|
|
rec.state = 'transferred'
|
|
|
|
def action_release(self):
|
|
for rec in self.filtered(lambda r: r.state == 'reserved'):
|
|
rec.state = 'available'
|