summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzka Nathan <darizkyfaz@gmail.com>2025-01-25 08:46:54 +0700
committerAzka Nathan <darizkyfaz@gmail.com>2025-01-25 08:46:54 +0700
commit43f0f79f96233e0b7b31b643e27d50887266a527 (patch)
treeea56302e2d28a4b57c0f1fab721c00c30cc3b15a
parentca9775c274d5e3de8f60abd66f14fa4fcb44a4ab (diff)
parent8af596373c8eb997bbb96cf020f670b6b60b57ca (diff)
Merge branch 'dev/wms' into odoo-production
# Conflicts: # indoteknik_custom/models/__init__.py
-rwxr-xr-xindoteknik_custom/__manifest__.py2
-rwxr-xr-xindoteknik_custom/models/__init__.py1
-rw-r--r--indoteknik_custom/models/barcoding_product.py37
-rwxr-xr-xindoteknik_custom/models/product_template.py2
-rw-r--r--indoteknik_custom/models/stock_move.py4
-rw-r--r--indoteknik_custom/models/stock_picking.py261
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv4
-rw-r--r--indoteknik_custom/views/barcoding_product.xml73
-rw-r--r--indoteknik_custom/views/stock_backorder_confirmation_views.xml14
-rw-r--r--indoteknik_custom/views/stock_picking.xml23
10 files changed, 368 insertions, 53 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 2e8ecbc1..e74efb95 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -151,6 +151,8 @@
'views/form_vendor_approval_multi_approve.xml',
'views/form_vendor_approval_multi_reject.xml',
'views/user_pengajuan_tempo.xml',
+ 'views/stock_backorder_confirmation_views.xml',
+ 'views/barcoding_product.xml',
'report/report.xml',
'report/report_banner_banner.xml',
'report/report_banner_banner2.xml',
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index 76e4611c..ddbe16f1 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -141,3 +141,4 @@ from . import va_multi_reject
from . import stock_immediate_transfer
from . import coretax_fatur
from . import ir_actions_report
+from . import barcoding_product
diff --git a/indoteknik_custom/models/barcoding_product.py b/indoteknik_custom/models/barcoding_product.py
new file mode 100644
index 00000000..6bbf9fde
--- /dev/null
+++ b/indoteknik_custom/models/barcoding_product.py
@@ -0,0 +1,37 @@
+from odoo import models, api, fields
+from odoo.exceptions import AccessError, UserError, ValidationError
+from datetime import timedelta, date, datetime
+import logging
+
+_logger = logging.getLogger(__name__)
+
+class BarcodingProduct(models.Model):
+ _name = "barcoding.product"
+ _description = "Barcoding Product"
+
+ barcoding_product_line = fields.One2many('barcoding.product.line', 'barcoding_product_id', string='Barcoding Product Lines', auto_join=True)
+ product_id = fields.Many2one('product.product', string="Product", tracking=3)
+ quantity = fields.Float(string="Quantity", tracking=3)
+
+ @api.onchange('product_id', 'quantity')
+ def _onchange_product_or_quantity(self):
+ """Update barcoding_product_line based on product_id and quantity"""
+ if self.product_id and self.quantity > 0:
+ # Clear existing lines
+ self.barcoding_product_line = [(5, 0, 0)]
+
+ # Add a new line with the current product and quantity
+ self.barcoding_product_line = [(0, 0, {
+ 'product_id': self.product_id.id,
+ 'barcoding_product_id': self.id,
+ }) for _ in range(int(self.quantity))]
+
+
+class BarcodingProductLine(models.Model):
+ _name = 'barcoding.product.line'
+ _description = 'Barcoding Product Line'
+ _order = 'barcoding_product_id, id'
+
+ barcoding_product_id = fields.Many2one('barcoding.product', string='Barcoding Product Ref', required=True, ondelete='cascade', index=True, copy=False)
+ product_id = fields.Many2one('product.product', string="Product")
+ qr_code_variant = fields.Binary("QR Code Variant", related='product_id.qr_code_variant') \ No newline at end of file
diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py
index 5bedae13..29608297 100755
--- a/indoteknik_custom/models/product_template.py
+++ b/indoteknik_custom/models/product_template.py
@@ -416,7 +416,7 @@ class ProductProduct(models.Model):
box_size=5,
border=4,
)
- qr.add_data(rec.default_code)
+ qr.add_data(rec.barcode if rec.barcode else rec.default_code)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py
index e1d4e74c..6b631713 100644
--- a/indoteknik_custom/models/stock_move.py
+++ b/indoteknik_custom/models/stock_move.py
@@ -12,9 +12,13 @@ class StockMove(models.Model):
default=lambda self: self.product_id.print_barcode,
)
qr_code_variant = fields.Binary("QR Code Variant", compute='_compute_qr_code_variant')
+ barcode = fields.Char(string='Barcode', related='product_id.barcode')
def _compute_qr_code_variant(self):
for rec in self:
+ if rec.picking_id.picking_type_code == 'outgoing' and rec.picking_id and rec.picking_id.origin and rec.picking_id.origin.startswith('SO/'):
+ rec.qr_code_variant = rec.product_id.qr_code_variant
+ rec.print_barcode = True
if rec.print_barcode and rec.print_barcode == True and rec.product_id and rec.product_id.qr_code_variant:
rec.qr_code_variant = rec.product_id.qr_code_variant
else:
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index cd330aeb..cc86c451 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -16,7 +16,8 @@ _logger = logging.getLogger(__name__)
class StockPicking(models.Model):
_inherit = 'stock.picking'
- # check_product_lines = fields.One2many('check.product', 'picking_id', string='Check Product', auto_join=True)
+ check_product_lines = fields.One2many('check.product', 'picking_id', string='Check Product', auto_join=True)
+ barcode_product_lines = fields.One2many('barcode.product', 'picking_id', string='Barcode Product', auto_join=True)
is_internal_use = fields.Boolean('Internal Use', help='flag which is internal use or not')
account_id = fields.Many2one('account.account', string='Account')
efaktur_id = fields.Many2one('vit.efaktur', string='Faktur Pajak')
@@ -176,7 +177,8 @@ class StockPicking(models.Model):
pickings = self.env['stock.picking'].search([
('picking_type_code', '=', 'outgoing'),
('state', '=', 'done'),
- ('carrier_id', '=', 9)
+ ('carrier_id', '=', 9),
+ ('lalamove_order_id', '!=', False)
])
for picking in pickings:
try:
@@ -810,7 +812,24 @@ class StockPicking(models.Model):
self.date_done = datetime.datetime.utcnow()
self.state_reserve = 'done'
return res
-
+
+
+ def check_qty_done_stock(self):
+ for line in self.move_line_ids_without_package:
+ def check_qty_per_inventory(self, product, location):
+ quant = self.env['stock.quant'].search([
+ ('product_id', '=', product.id),
+ ('location_id', '=', location.id),
+ ])
+
+ if quant:
+ return quant.quantity
+
+ return 0
+
+ qty_onhand = check_qty_per_inventory(self, line.product_id, line.location_id)
+ if line.qty_done > qty_onhand:
+ raise UserError('Quantity Done melebihi Quantity Onhand')
def send_mail_bills(self):
if self.picking_type_code == 'incoming' and self.purchase_id:
@@ -875,10 +894,39 @@ class StockPicking(models.Model):
@api.model
def create(self, vals):
self._use_faktur(vals)
+ if vals.get('picking_type_code') == 'incoming' and vals.get('location_dest_id') == 58:
+ if 'name' in vals and vals['name'].startswith('BU/IN/'):
+ vals['name'] = vals['name'].replace('BU/IN/', 'BU/INPUT/', 1)
+
+ if vals.get('picking_type_code') == 'internal' and vals.get('location_id') == 58:
+ if 'name' in vals and vals['name'].startswith('BU/INT'):
+ new_name = vals['name'].replace('BU/INT', 'BU/IN', 1)
+ # Periksa apakah nama sudah ada
+ if self.env['stock.picking'].search_count([('name', '=', new_name), ('company_id', '=', vals.get('company_id'))]) > 0:
+ new_name = f"{new_name}-DUP"
+ vals['name'] = new_name
return super(StockPicking, self).create(vals)
def write(self, vals):
self._use_faktur(vals)
+ for picking in self:
+ # Periksa apakah kondisi terpenuhi saat data diubah
+ if (vals.get('picking_type_code', picking.picking_type_code) == 'incoming' and
+ vals.get('location_dest_id', picking.location_dest_id.id) == 58):
+ if 'name' in vals or picking.name.startswith('BU/IN/'):
+ name_to_modify = vals.get('name', picking.name)
+ if name_to_modify.startswith('BU/IN/'):
+ vals['name'] = name_to_modify.replace('BU/IN/', 'BU/INPUT/', 1)
+
+ if (vals.get('picking_type_code', picking.picking_type_code) == 'internal' and
+ vals.get('location_id', picking.location_id.id) == 58):
+ name_to_modify = vals.get('name', picking.name)
+ if name_to_modify.startswith('BU/INT'):
+ new_name = name_to_modify.replace('BU/INT', 'BU/IN', 1)
+ # Periksa apakah nama sudah ada
+ if self.env['stock.picking'].search_count([('name', '=', new_name), ('company_id', '=', picking.company_id.id)]) > 0:
+ new_name = f"{new_name}-DUP"
+ vals['name'] = new_name
return super(StockPicking, self).write(vals)
def _use_faktur(self, vals):
@@ -1008,48 +1056,165 @@ class StockPicking(models.Model):
return f'{formatted_fastest_eta} - {formatted_longest_eta}'
-# class CheckProduct(models.Model):
-# _name = 'check.product'
-# _description = 'Check Product'
-# _order = 'picking_id, id'
-
-# picking_id = fields.Many2one('stock.picking', string='Picking Reference', required=True, ondelete='cascade', index=True, copy=False)
-# product_id = fields.Many2one('product.product', string='Product')
-
-
-# @api.constrains('product_id')
-# def check_product_validity(self):
-# """
-# Validate if the product exists in the related stock.picking's move_ids_without_package
-# and ensure that the product's quantity does not exceed the available product_uom_qty.
-# """
-# for record in self:
-# if not record.picking_id or not record.product_id:
-# continue
-
-# # Filter move lines in the related picking for the selected product
-# moves = record.picking_id.move_ids_without_package.filtered(
-# lambda move: move.product_id.id == record.product_id.id
-# )
-
-# if not moves:
-# raise UserError((
-# "The product '%s' is not available in the related stock picking's moves. "
-# "Please check and try again."
-# ) % record.product_id.display_name)
-
-# # Calculate the total entries for the product in check.product for the same picking
-# product_entries_count = self.search_count([
-# ('picking_id', '=', record.picking_id.id),
-# ('product_id', '=', record.product_id.id)
-# ])
-
-# # Sum the product_uom_qty for all relevant moves
-# total_qty_in_moves = sum(moves.mapped('product_uom_qty'))
-
-# # Compare the count of entries against the available quantity
-# if product_entries_count > total_qty_in_moves:
-# raise UserError((
-# "The product '%s' exceeds the allowable quantity (%s) in the related stock picking's moves. "
-# "You can only add it %s times."
-# ) % (record.product_id.display_name, total_qty_in_moves, total_qty_in_moves))
+class CheckProduct(models.Model):
+ _name = 'check.product'
+ _description = 'Check Product'
+ _order = 'picking_id, id'
+
+ picking_id = fields.Many2one(
+ 'stock.picking',
+ string='Picking Reference',
+ required=True,
+ ondelete='cascade',
+ index=True,
+ copy=False,
+ )
+ product_id = fields.Many2one('product.product', string='Product', required=True)
+ quantity = fields.Float(string='Quantity', default=1.0, required=True)
+ status = fields.Char(string='Status', compute='_compute_status')
+
+ @api.depends('quantity')
+ def _compute_status(self):
+ for record in self:
+ moves = record.picking_id.move_ids_without_package.filtered(
+ lambda move: move.product_id.id == record.product_id.id
+ )
+ total_qty_in_moves = sum(moves.mapped('product_uom_qty'))
+
+ if record.quantity < total_qty_in_moves:
+ record.status = 'Pending'
+ else:
+ record.status = 'Done'
+
+
+ def create(self, vals):
+ # Create the record
+ record = super(CheckProduct, self).create(vals)
+ # Ensure uniqueness after creation
+ if not self.env.context.get('skip_consolidate'):
+ record.with_context(skip_consolidate=True)._consolidate_duplicate_lines()
+ return record
+
+ def write(self, vals):
+ # Write changes to the record
+ result = super(CheckProduct, self).write(vals)
+ # Ensure uniqueness after writing
+ if not self.env.context.get('skip_consolidate'):
+ self.with_context(skip_consolidate=True)._consolidate_duplicate_lines()
+ return result
+
+ def _sync_check_product_to_moves(self, picking):
+ """
+ Sinkronisasi quantity_done di move_ids_without_package
+ dengan total quantity dari check.product berdasarkan product_id.
+ """
+ for product_id in picking.check_product_lines.mapped('product_id'):
+ # Totalkan quantity dari semua baris check.product untuk product_id ini
+ total_quantity = sum(
+ line.quantity for line in picking.check_product_lines.filtered(lambda line: line.product_id == product_id)
+ )
+ # Update quantity_done di move yang relevan
+ moves = picking.move_ids_without_package.filtered(lambda move: move.product_id == product_id)
+ for move in moves:
+ move.quantity_done = total_quantity
+
+ def _consolidate_duplicate_lines(self):
+ """
+ Consolidate duplicate lines with the same product_id under the same picking_id
+ and sync the total quantity to related moves.
+ """
+ for picking in self.mapped('picking_id'):
+ lines_to_remove = self.env['check.product'] # Recordset untuk menyimpan baris yang akan dihapus
+ product_lines = picking.check_product_lines.filtered(lambda line: line.product_id)
+
+ # Group lines by product_id
+ product_groups = {}
+ for line in product_lines:
+ product_groups.setdefault(line.product_id.id, []).append(line)
+
+ for product_id, lines in product_groups.items():
+ if len(lines) > 1:
+ # Consolidate duplicate lines
+ first_line = lines[0]
+ total_quantity = sum(line.quantity for line in lines)
+
+ # Update the first line's quantity
+ first_line.with_context(skip_consolidate=True).write({'quantity': total_quantity})
+
+ # Add the remaining lines to the lines_to_remove recordset
+ lines_to_remove |= self.env['check.product'].browse([line.id for line in lines[1:]])
+
+ # Perform unlink after consolidation
+ if lines_to_remove:
+ lines_to_remove.unlink()
+
+ # Sync total quantities to moves
+ self._sync_check_product_to_moves(picking)
+
+ @api.onchange('product_id', 'quantity')
+ def check_product_validity(self):
+ for record in self:
+ if not record.picking_id or not record.product_id:
+ continue
+
+ # Filter moves related to the selected product
+ moves = record.picking_id.move_ids_without_package.filtered(
+ lambda move: move.product_id.id == record.product_id.id
+ )
+
+ if not moves:
+ raise UserError((
+ "The product '%s' tidak ada di operations. "
+ ) % record.product_id.display_name)
+
+ total_qty_in_moves = sum(moves.mapped('product_uom_qty'))
+
+ # Find existing lines for the same product, excluding the current line
+ existing_lines = record.picking_id.check_product_lines.filtered(
+ lambda line: line.product_id == record.product_id and line.id != record.id
+ )
+
+ if existing_lines:
+ # Get the first existing line
+ first_line = existing_lines[0]
+
+ # Calculate the total quantity after addition
+ total_quantity = sum(existing_lines.mapped('quantity')) - record.quantity
+
+ if total_quantity > total_qty_in_moves:
+ raise UserError((
+ "Quantity Product '%s' sudah melebihi quantity demand."
+ ) % (record.product_id.display_name))
+ else:
+ # Check if the quantity exceeds the allowed total
+ if record.quantity > total_qty_in_moves:
+ raise UserError((
+ "Quantity Product '%s' sudah melebihi quantity demand."
+ ) % (record.product_id.display_name))
+
+ # Set the quantity to the entered value
+ record.quantity = record.quantity
+
+class BarcodeProduct(models.Model):
+ _name = 'barcode.product'
+ _description = 'Barcode Product'
+ _order = 'picking_id, id'
+
+ picking_id = fields.Many2one(
+ 'stock.picking',
+ string='Picking Reference',
+ required=True,
+ ondelete='cascade',
+ index=True,
+ copy=False,
+ )
+ product_id = fields.Many2one('product.product', string='Product', required=True)
+ barcode = fields.Char(string='Barcode')
+
+ @api.constrains('barcode')
+ def send_barcode_to_product(self):
+ for record in self:
+ if record.barcode and not record.product_id.barcode:
+ record.product_id.barcode = record.barcode
+ else:
+ raise UserError('Barcode sudah terisi') \ No newline at end of file
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 188a9619..d4b79cd9 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -150,6 +150,7 @@ access_sales_order_fulfillment_v2,access.sales.order.fulfillment.v2,model_sales_
access_v_move_outstanding,access.v.move.outstanding,model_v_move_outstanding,,1,1,1,1
access_va_multi_approve,access.va.multi.approve,model_va_multi_approve,,1,1,1,1
access_va_multi_reject,access.va.multi.reject,model_va_multi_reject,,1,1,1,1
+access_check_product,access.check.product,model_check_product,,1,1,1,1
access_stock_immediate_transfer,access.stock.immediate.transfer,model_stock_immediate_transfer,,1,1,1,1
access_coretax_faktur,access.coretax.faktur,model_coretax_faktur,,1,1,1,1
access_purchase_order_unlock_wizard,access.purchase.order.unlock.wizard,model_purchase_order_unlock_wizard,,1,1,1,1
@@ -158,3 +159,6 @@ access_User_pengajuan_tempo_line,access.user.pengajuan.tempo.line,model_user_pen
access_user_pengajuan_tempo,access.user.pengajuan.tempo,model_user_pengajuan_tempo,,1,1,1,1
access_reject_reason_wizard,reject.reason.wizard,model_reject_reason_wizard,,1,1,1,0
access_confirm_approval_wizard,confirm.approval.wizard,model_confirm_approval_wizard,,1,1,1,0
+access_barcode_product,access.barcode.product,model_barcode_product,,1,1,1,1
+access_barcoding_product,access.barcoding.product,model_barcoding_product,,1,1,1,1
+access_barcoding_product_line,access.barcoding.product.line,model_barcoding_product_line,,1,1,1,1 \ No newline at end of file
diff --git a/indoteknik_custom/views/barcoding_product.xml b/indoteknik_custom/views/barcoding_product.xml
new file mode 100644
index 00000000..566655ff
--- /dev/null
+++ b/indoteknik_custom/views/barcoding_product.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<odoo>
+ <data>
+ <record id="barcoding_product_tree" model="ir.ui.view">
+ <field name="name">barcoding.product.tree</field>
+ <field name="model">barcoding.product</field>
+ <field name="arch" type="xml">
+ <tree default_order="create_date desc">
+ <field name="product_id"/>
+ <field name="quantity"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="barcoding_product_line_tree" model="ir.ui.view">
+ <field name="name">barcoding.product.line.tree</field>
+ <field name="model">barcoding.product.line</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="product_id"/>
+ <field name="qr_code_variant" widget="image"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="barcoding_product_form" model="ir.ui.view">
+ <field name="name">barcoding.product.form</field>
+ <field name="model">barcoding.product</field>
+ <field name="arch" type="xml">
+ <form >
+ <sheet>
+ <group>
+ <group>
+ <field name="product_id" required="1"/>
+ <field name="quantity" required="1"/>
+ </group>
+ </group>
+ <notebook>
+ <page string="Line">
+ <field name="barcoding_product_line"/>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="barcoding_product_view_search" model="ir.ui.view">
+ <field name="name">barcoding.product.search.view</field>
+ <field name="model">barcoding.product</field>
+ <field name="arch" type="xml">
+ <search string="Search Barcoding Product">
+ <field name="product_id"/>
+ </search>
+ </field>
+ </record>
+
+ <record id="barcoding_product_action" model="ir.actions.act_window">
+ <field name="name">Barcoding Product</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">barcoding.product</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem
+ id="menu_barcoding_product"
+ name="Barcoding Product"
+ parent="stock.menu_stock_warehouse_mgmt"
+ sequence="4"
+ action="barcoding_product_action"
+ />
+ </data>
+</odoo>
diff --git a/indoteknik_custom/views/stock_backorder_confirmation_views.xml b/indoteknik_custom/views/stock_backorder_confirmation_views.xml
new file mode 100644
index 00000000..a622899e
--- /dev/null
+++ b/indoteknik_custom/views/stock_backorder_confirmation_views.xml
@@ -0,0 +1,14 @@
+<odoo>
+ <record id="view_backorder_confirmation_inherit" model="ir.ui.view">
+ <field name="name">stock_backorder_confirmation_inherit</field>
+ <field name="model">stock.backorder.confirmation</field>
+ <field name="inherit_id" ref="stock.view_backorder_confirmation"/>
+ <field name="arch" type="xml">
+ <xpath expr="//group/p[1]" position="replace">
+ <p>
+ Ada product yang quantity done nya kurang dari quantity demand.
+ </p>
+ </xpath>
+ </field>
+ </record>
+</odoo>
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index 38ce1af5..50ea40bf 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -132,6 +132,7 @@
<field name="sale_id" attrs="{'readonly': 1}" optional="hide"/>
<field name="print_barcode" optional="hide"/>
<field name="qr_code_variant" widget="image" optional="hide"/>
+ <field name="barcode" optional="hide"/>
</field>
<page name="note" position="after">
<page string="E-Faktur" name="efaktur" attrs="{'invisible': [['is_internal_use', '=', False]]}">
@@ -191,15 +192,18 @@
</group>
</group>
</page>
- <!-- <page string="Check Product" name="check_product">
+ <page string="Check Product" name="check_product">
<field name="check_product_lines"/>
- </page> -->
+ </page>
+ <page string="Barcode Product" name="barcode_product" attrs="{'invisible': [('picking_type_code', '!=', 'incoming')]}">
+ <field name="barcode_product_lines"/>
+ </page>
</page>
</field>
</record>
- <!-- <record id="check_product_tree" model="ir.ui.view">
+ <record id="check_product_tree" model="ir.ui.view">
<field name="name">check.product.tree</field>
<field name="model">check.product</field>
<field name="arch" type="xml">
@@ -209,7 +213,18 @@
<field name="status"/>
</tree>
</field>
- </record> -->
+ </record>
+
+ <record id="barcode_product_tree" model="ir.ui.view">
+ <field name="name">barcode.product.tree</field>
+ <field name="model">barcode.product</field>
+ <field name="arch" type="xml">
+ <tree editable="bottom">
+ <field name="product_id"/>
+ <field name="barcode"/>
+ </tree>
+ </field>
+ </record>
<record id="view_stock_move_line_detailed_operation_tree_inherit" model="ir.ui.view">
<field name="name">stock.move.line.operations.tree.inherit</field>