feat: Add subcontract lot generation wizard and UI buttons to stock pickings and moves, including validation for cancelled manufacturing orders.
This commit is contained in:
parent
56cd97ef27
commit
de4f502d01
@ -5,6 +5,7 @@ This Odoo 19 module provides automated lot/serial number generation specifically
|
||||
|
||||
## Features
|
||||
- **Auto-Generate Lots**: Automatically generates lot/serial numbers for subcontract receipt moves based on the product's configured sequence.
|
||||
- **Validation Check**: Prevents lot generation if the linked Subcontract Manufacturing Order is cancelled, alerting the user to potential data inconsistency.
|
||||
- **Wizard Support**: Includes a "Generate Subcontract Lots" wizard for manual control and batch generation.
|
||||
- **Validation Hook**: Automatically triggers lot generation when validating a subcontracting receipt (Stock Picking).
|
||||
- **Native Compatibility**: Uses Odoo 19's standard `lot_sequence_id` on the product template, ensuring no conflict with standard features.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
|
||||
from odoo import api, models, _
|
||||
from odoo.exceptions import UserError
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@ -11,9 +13,24 @@ class StockMove(models.Model):
|
||||
"""
|
||||
Auto-generate lot numbers for subcontracting moves.
|
||||
This method handles the automatic lot generation for subcontracted products.
|
||||
It also validates that the linked Manufacturing Order is not cancelled.
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
if getattr(self, 'is_subcontract', False):
|
||||
# Check for cancelled subcontract MOs
|
||||
# We use getattr/safe access or rely on the fact that this module depends on mrp_subcontracting
|
||||
productions = self._get_subcontract_production()
|
||||
cancelled_productions = productions.filtered(lambda p: p.state == 'cancel')
|
||||
if cancelled_productions:
|
||||
raise UserError(_(
|
||||
"Cannot generate lots for product %s.\n"
|
||||
"The linked Subcontracting Manufacturing Order (e.g., %s) is cancelled.\n"
|
||||
"Lots generated would not be correctly linked to the receipt quantity.\n"
|
||||
"Please check the Manufacturing Order status."
|
||||
) % (self.product_id.display_name, cancelled_productions[0].name))
|
||||
|
||||
|
||||
if not self.product_id.tracking in ['lot', 'serial']:
|
||||
return []
|
||||
|
||||
|
||||
2
security/ir.model.access.csv
Normal file
2
security/ir.model.access.csv
Normal file
@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_subcontract_lot_generator,subcontract.lot.generator,model_subcontract_lot_generator,base.group_user,1,1,1,1
|
||||
|
20
views/stock_move_views.xml
Normal file
20
views/stock_move_views.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Add menu item to stock move -->
|
||||
<record id="view_stock_move_form_inherit_lot_generation" model="ir.ui.view">
|
||||
<field name="name">stock.move.form.inherit.lot.generation</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header" position="inside">
|
||||
<button name="action_generate_lots_for_move"
|
||||
type="object"
|
||||
string="Generate Lots"
|
||||
class="btn-secondary"
|
||||
icon="fa-plus"
|
||||
invisible="not is_subcontract"
|
||||
help="Generate lot/serial numbers for this subcontract move"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
69
views/stock_picking_views.xml
Normal file
69
views/stock_picking_views.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Add auto-generate lots button to subcontracting receipt forms -->
|
||||
<record id="view_picking_form_inherit_subcontract_lots" model="ir.ui.view">
|
||||
<field name="name">stock.picking.form.inherit.subcontract.lots</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Add invisible fields for computed values -->
|
||||
<xpath expr="//form" position="inside">
|
||||
<field name="has_subcontract_moves" invisible="1"/>
|
||||
</xpath>
|
||||
<!-- Add the auto-generate button in the header for subcontract receipts -->
|
||||
<xpath expr="//header" position="inside">
|
||||
<button name="action_auto_generate_lots_subcontract"
|
||||
type="object"
|
||||
string="Auto Generate Lots"
|
||||
class="btn-secondary"
|
||||
icon="fa-plus"
|
||||
invisible="picking_type_code != 'incoming' or not has_subcontract_moves"
|
||||
help="Automatically generate lot/serial numbers for subcontracted products"/>
|
||||
<button name="action_open_subcontract_lot_wizard"
|
||||
type="object"
|
||||
string="Advanced Lot Generation"
|
||||
class="btn-secondary"
|
||||
icon="fa-cogs"
|
||||
invisible="picking_type_code != 'incoming' or not has_subcontract_moves"
|
||||
help="Advanced lot generation with custom options"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Enhance the move lines view to show auto-generate option -->
|
||||
<record id="view_stock_move_line_detailed_operation_inherit" model="ir.ui.view">
|
||||
<field name="name">stock.move.line.detailed.operation.inherit.subcontract</field>
|
||||
<field name="model">stock.move.line</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_move_line_detailed_operation_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Add a button in the move line tree for individual lot generation -->
|
||||
<xpath expr="//field[@name='lot_name']" position="after">
|
||||
<button name="action_open_lot_generator"
|
||||
type="object"
|
||||
icon="fa-plus"
|
||||
class="btn-link"
|
||||
context="{'default_product_id': product_id, 'default_move_id': move_id}"
|
||||
invisible="not product_id"
|
||||
help="Generate lot/serial numbers"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Add a smart button to show generated lots for subcontract moves -->
|
||||
<record id="view_picking_form_subcontract_lots_smart_button" model="ir.ui.view">
|
||||
<field name="name">stock.picking.form.subcontract.lots.smart.button</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button type="object"
|
||||
name="action_view_generated_lots"
|
||||
class="oe_stat_button"
|
||||
icon="fa-barcode"
|
||||
invisible="picking_type_code != 'incoming' or not has_subcontract_moves">
|
||||
<field name="subcontract_lot_count" widget="statinfo" string="Generated Lots"/>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
40
wizard/subcontract_lot_generator_views.xml
Normal file
40
wizard/subcontract_lot_generator_views.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Subcontract Lot Generator Wizard Form -->
|
||||
<record id="view_subcontract_lot_generator_form" model="ir.ui.view">
|
||||
<field name="name">subcontract.lot.generator.form</field>
|
||||
<field name="model">subcontract.lot.generator</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Generate Lots for Subcontract">
|
||||
<group>
|
||||
<group>
|
||||
<field name="picking_id" readonly="1"/>
|
||||
<field name="move_id" readonly="1"/>
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="tracking" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="quantity"/>
|
||||
<field name="lot_count" readonly="tracking == 'serial'"/>
|
||||
<field name="use_sequence"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_generate_lots" type="object" string="Generate Lots" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Action for the wizard -->
|
||||
<record id="action_subcontract_lot_generator" model="ir.actions.act_window">
|
||||
<field name="name">Generate Subcontract Lots</field>
|
||||
<field name="res_model">subcontract.lot.generator</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{
|
||||
'default_picking_id': active_id,
|
||||
}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue
Block a user