[IMP] stock: move detailed operation view to smart button

After this commit, detailed operations is no longer a tab in the picking
but under a smart button in the form.

The field `show_operations` on picking type is no longer useful and will
be removed in a later PR targeting master

closes odoo/odoo#140898

Taskid: 3486636
Related: odoo/enterprise#50805
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
Ahmed Khalaf
2023-11-20 11:13:13 +00:00
parent 083cd011a1
commit 5a69ef6e04
21 changed files with 120 additions and 157 deletions
+5
View File
@@ -101,6 +101,11 @@ class StockPicking(models.Model):
for picking in self:
picking.has_kits = any(picking.move_ids.mapped('bom_line_id'))
def action_detailed_operations(self):
action = super().action_detailed_operations()
action['context']['has_kits'] = self.has_kits
return action
def _less_quantities_than_expected_add_documents(self, moves, documents):
documents = super(StockPicking, self)._less_quantities_than_expected_add_documents(moves, documents)
+3 -2
View File
@@ -122,8 +122,9 @@ class TestMrpStockReports(TestReportsCommon):
mo_1.action_confirm()
pick = mo_1.move_raw_ids.move_orig_ids.picking_id
pick_form = Form(pick)
with pick_form.move_line_ids_without_package.edit(0) as move_line:
move_line.quantity = 20
with Form(pick.move_ids_without_package, view='stock.view_stock_move_operations') as form:
with form.move_line_ids.edit(0) as move_line:
move_line.quantity = 20
pick = pick_form.save()
pick.button_validate()
# Produces 3 products then creates a backorder for the remaining product.
+1 -1
View File
@@ -119,7 +119,7 @@
<field name="inherit_id" ref="stock.view_stock_move_line_detailed_operation_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_id']" position="after">
<field name="description_bom_line" optional="show" column_invisible="not parent.has_kits"/>
<field name="description_bom_line" optional="show" column_invisible="not context.get('has_kits')"/>
</xpath>
</field>
</record>
@@ -38,7 +38,6 @@ class Warehouse(models.Model):
'sequence': max_sequence + 1,
'sequence_code': 'POS',
'company_id': self.company_id.id,
'show_operations': False,
}
})
return picking_type_create_values, max_sequence + 2
@@ -38,7 +38,7 @@
<field name="arch" type="xml">
<xpath expr="//field[@name='lot_name']" position="after">
<field name="picking_type_use_existing_lots" column_invisible="True"/>
<field name="expiration_date" force_save="1" column_invisible="parent.picking_type_code != 'incoming'" readonly="picking_type_use_existing_lots"/>
<field name="expiration_date" force_save="1" column_invisible="context.get('picking_code') != 'incoming'" readonly="picking_type_use_existing_lots"/>
</xpath>
<xpath expr="//field[@name='lot_id']" position="after">
<field name="is_expired" column_invisible="True"/>
-1
View File
@@ -143,7 +143,6 @@
<field name="picking_code" column_invisible="True"/>
<field name="product_type" column_invisible="True"/>
<field name="show_details_visible" column_invisible="True"/>
<field name="show_operations" readonly="1" column_invisible="True"/>
<field name="additional" column_invisible="True"/>
<field name="move_lines_count" column_invisible="True"/>
<field name="is_locked" column_invisible="True"/>
+10 -10
View File
@@ -712,9 +712,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
initial_product = sale_order.order_line.product_id
picking_form = Form(picking)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 5
with picking_form.move_line_ids_without_package.new() as new_move:
with picking_form.move_ids_without_package.new() as new_move:
new_move.product_id = product_inv_on_order
new_move.quantity = 5
picking = picking_form.save()
@@ -753,9 +753,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
picking = sale_order.picking_ids
picking_form = Form(picking)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 5
with picking_form.move_line_ids_without_package.new() as new_move:
with picking_form.move_ids_without_package.new() as new_move:
new_move.product_id = product_inv_on_delivered
new_move.quantity = 5
picking = picking_form.save()
@@ -803,14 +803,14 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
delivery = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'outgoing')
picking_form = Form(pick)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 10
pick = picking_form.save()
pick.move_ids.picked = True
pick.button_validate()
picking_form = Form(delivery)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 10
delivery = picking_form.save()
delivery.move_ids.picked = True
@@ -833,9 +833,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
delivery = sale_order.picking_ids.filtered(lambda p: p.picking_type_code == 'outgoing')
picking_form = Form(pick)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 10
with picking_form.move_line_ids_without_package.new() as new_move:
with picking_form.move_ids_without_package.new() as new_move:
new_move.product_id = product_inv_on_order
new_move.quantity = 10
pick = picking_form.save()
@@ -843,9 +843,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
pick.button_validate()
picking_form = Form(delivery)
with picking_form.move_line_ids_without_package.edit(0) as move:
with picking_form.move_ids_without_package.edit(0) as move:
move.quantity = 10
with picking_form.move_line_ids_without_package.new() as new_move:
with picking_form.move_ids_without_package.new() as new_move:
new_move.product_id = product_inv_on_order
new_move.quantity = 10
delivery = picking_form.save()
@@ -93,7 +93,6 @@ class ResConfigSettings(models.TransientModel):
putaway_rules.active = False
previous_group = self.default_get(['group_stock_multi_locations', 'group_stock_production_lot', 'group_stock_tracking_lot'])
was_operations_showed = self.env['stock.picking.type'].with_user(SUPERUSER_ID)._default_show_operations()
super().set_values()
if not self.user_has_groups('stock.group_stock_manager'):
@@ -128,12 +127,6 @@ class ResConfigSettings(models.TransientModel):
if view:
view.active = True
if not was_operations_showed and self.env['stock.picking.type'].with_user(SUPERUSER_ID)._default_show_operations():
self.env['stock.picking.type'].with_context(active_test=False).sudo().search([
('code', '!=', 'incoming'),
('show_operations', '=', False)
]).show_operations = True
if not self.group_stock_production_lot and previous_group.get('group_stock_production_lot'):
if self.env['product.product'].search_count([('tracking', '!=', 'none')], limit=1):
raise UserError(_("You have product(s) in stock that have lot/serial number tracking enabled. \nSwitch off tracking on all the products before switching off this setting."))
+1
View File
@@ -155,6 +155,7 @@ class StockMove(models.Model):
has_tracking = fields.Selection(related='product_id.tracking', string='Product with Tracking')
quantity = fields.Float(
'Quantity', compute='_compute_quantity', digits='Product Unit of Measure', inverse='_set_quantity', store=True)
# TODO: delete this field `show_operations`
show_operations = fields.Boolean(related='picking_id.picking_type_id.show_operations')
picking_code = fields.Selection(related='picking_id.picking_type_id.code', readonly=True)
show_details_visible = fields.Boolean('Details Visible', compute='_compute_show_details_visible')
+7
View File
@@ -84,6 +84,8 @@ class StockMoveLine(models.Model):
description_picking = fields.Text(string="Description picking")
quant_id = fields.Many2one('stock.quant', "Pick From", store=False) # Dummy field for the detailed operation view
product_packaging_qty = fields.Float(string="Reserved Packaging Quantity", compute='_compute_product_packaging_qty')
picking_location_id = fields.Many2one(related='picking_id.location_id')
picking_location_dest_id = fields.Many2one(related='picking_id.location_dest_id')
@api.depends('product_uom_id.category_id', 'product_id.uom_id.category_id', 'move_id.product_uom', 'product_id.uom_id')
def _compute_product_uom_id(self):
@@ -885,6 +887,11 @@ class StockMoveLine(models.Model):
'res_id': self.id,
}
def action_put_in_pack(self):
for picking in self.picking_id:
picking.action_put_in_pack()
return self.picking_id.action_detailed_operations()
def _get_revert_inventory_move_values(self):
self.ensure_one()
return {
+25 -33
View File
@@ -24,11 +24,6 @@ class PickingType(models.Model):
_rec_names_search = ['name', 'warehouse_id.name']
_check_company_auto = True
def _default_show_operations(self):
return self.user_has_groups('stock.group_production_lot,'
'stock.group_stock_multi_locations,'
'stock.group_tracking_lot')
name = fields.Char('Operation Type', required=True, translate=True)
color = fields.Integer('Color')
sequence = fields.Integer('Sequence', help="Used to order the 'All Operations' kanban view")
@@ -67,8 +62,9 @@ class PickingType(models.Model):
print_label = fields.Boolean(
'Print Label',
help="If this checkbox is ticked, label will be print in this operation.")
# TODO: delete this field `show_operations`
show_operations = fields.Boolean(
'Show Detailed Operations', default=_default_show_operations,
'Show Detailed Operations', default=False,
help="If this checkbox is ticked, the pickings lines will represent detailed stock operations. If not, the picking lines will represent an aggregate of detailed stock operations.")
show_reserved = fields.Boolean(
'Pre-fill Detailed Operations', default=True,
@@ -276,15 +272,6 @@ class PickingType(models.Model):
elif picking_type.code == 'outgoing':
picking_type.print_label = True
@api.depends('code')
def _compute_show_operations(self):
for picking_type in self:
picking_type.show_operations = picking_type.code != 'incoming' and picking_type.user_has_groups(
'stock.group_production_lot,'
'stock.group_stock_multi_locations,'
'stock.group_tracking_lot'
)
@api.onchange('code')
def _onchange_picking_code(self):
if self.code == 'internal' and not self.user_has_groups('stock.group_stock_multi_locations'):
@@ -305,10 +292,10 @@ class PickingType(models.Model):
else:
picking_type.warehouse_id = False
@api.depends('show_operations', 'code')
@api.depends('code')
def _compute_show_reserved(self):
for picking_type in self:
if picking_type.show_operations and picking_type.code != 'incoming':
if picking_type.code != 'incoming':
picking_type.show_reserved = True
@api.constrains('default_location_dest_id')
@@ -503,8 +490,8 @@ class Picking(models.Model):
# Used to search on pickings
product_id = fields.Many2one('product.product', 'Product', related='move_ids.product_id', readonly=True)
lot_id = fields.Many2one('stock.lot', 'Lot/Serial Number', related='move_line_ids.lot_id', readonly=True)
show_operations = fields.Boolean(compute='_compute_show_operations')
# TODO: delete this field `show_operations`
show_operations = fields.Boolean(related='picking_type_id.show_operations')
show_reserved = fields.Boolean(related='picking_type_id.show_reserved')
show_lots_text = fields.Boolean(compute='_compute_show_lots_text')
has_tracking = fields.Boolean(compute='_compute_has_tracking')
@@ -584,20 +571,6 @@ class Picking(models.Model):
picking.products_availability = _('Exp %s', format_date(self.env, forecast_date))
picking.products_availability_state = 'late' if picking.scheduled_date and picking.scheduled_date < forecast_date else 'expected'
@api.depends('picking_type_id.show_operations')
def _compute_show_operations(self):
for picking in self:
if self.env.context.get('force_detailed_view'):
picking.show_operations = True
continue
if picking.picking_type_id.show_operations:
if (picking.state == 'draft') or picking.state != 'draft':
picking.show_operations = True
else:
picking.show_operations = False
else:
picking.show_operations = False
@api.depends('move_line_ids', 'picking_type_id.use_create_lots', 'picking_type_id.use_existing_lots', 'state')
def _compute_show_lots_text(self):
group_production_lot_enabled = self.user_has_groups('stock.group_production_lot')
@@ -952,6 +925,25 @@ class Picking(models.Model):
self.filtered(lambda x: not x.move_ids).state = 'cancel'
return True
def action_detailed_operations(self):
view_id = self.env.ref('stock.view_stock_move_line_detailed_operation_tree').id
return {
'name': _('Detailed Operations'),
'view_mode': 'tree',
'type': 'ir.actions.act_window',
'res_model': 'stock.move.line',
'views': [(view_id, 'tree')],
'domain': [('id', 'in', self.move_line_ids.ids)],
'context': {
'default_picking_id': self.id,
'default_location_id': self.location_id.id,
'default_location_dest_id': self.location_dest_id.id,
'default_company_id': self.company_id.id,
'show_lots_text': self.show_lots_text,
'picking_code': self.picking_type_code,
}
}
def _action_done(self):
"""Call `_action_done` on the `stock.move` of the `stock.picking` in `self`.
This method makes sure every `stock.move.line` is linked to a `stock.move` by either
-1
View File
@@ -968,7 +968,6 @@ class Warehouse(models.Model):
'default_location_src_id': False,
'sequence': max_sequence + 1,
'show_reserved': False,
'show_operations': False,
'sequence_code': 'IN',
'company_id': self.company_id.id,
}, 'out_type_id': {
+1 -5
View File
@@ -354,11 +354,8 @@ class PickingType(models.Model):
yield values
def get_show_operations(values, counter, random):
return values['code'] != 'incoming' # Simulate onchange of form
def get_show_reserved(values, counter, random):
return values['show_operations'] and values['code'] != 'incoming' # Simulate onchange of form
return values['code'] != 'incoming' # Simulate onchange of form
return [
('company_id', populate.iterate(company_ids)),
@@ -366,7 +363,6 @@ class PickingType(models.Model):
('name', populate.compute(get_name)),
('sequence_code', populate.constant("PT{counter}")),
('_compute_default_locations', _compute_default_locations),
('show_operations', populate.compute(get_show_operations)),
('show_reserved', populate.compute(get_show_reserved)),
]
+3 -5
View File
@@ -5991,8 +5991,7 @@ class StockMove(TransactionCase):
def test_SML_location_selection(self):
"""
Suppose the setting 'Storage Categories' disabled and the option 'Show Detailed Operations'
for operation 'Internal Transfer' enabled.
Suppose the setting 'Storage Categories' disabled.
A user creates an internal transfer from F to T, confirms it then adds a SML and selects
another destination location L (with L a child of T). When the user completes the field
`quantity`, the onchange should n't change the destination location L
@@ -6000,7 +5999,6 @@ class StockMove(TransactionCase):
self.env.user.write({'groups_id': [(3, self.env.ref('stock.group_stock_storage_categories').id)]})
internal_transfer = self.env.ref('stock.picking_type_internal')
internal_transfer.show_operations = True
picking = self.env['stock.picking'].create({
'picking_type_id': internal_transfer.id,
@@ -6020,8 +6018,8 @@ class StockMove(TransactionCase):
picking.action_confirm()
with Form(picking) as form:
with form.move_line_ids_without_package.edit(0) as line:
with Form(picking.move_ids_without_package, view='stock.view_stock_move_operations') as form:
with form.move_line_ids.edit(0) as line:
line.location_dest_id = self.stock_location.child_ids[0]
line.quantity = 1
+10 -4
View File
@@ -2294,7 +2294,6 @@ class TestSinglePicking(TestStockCommon):
})
# Changes config of receipt type to allow to edit move lines directly.
picking_type = self.env['stock.picking.type'].browse(self.picking_type_in)
picking_type.show_operations = True
picking_type.show_reserved = True
receipt_form = Form(self.env['stock.picking'].with_context(
@@ -2306,9 +2305,16 @@ class TestSinglePicking(TestStockCommon):
receipt_form.location_dest_id = stock_location
receipt = receipt_form.save()
with receipt_form.move_line_ids_without_package.new() as move_line:
move_line.product_id = self.productA
move_line.quantity = 1.0
with receipt_form.move_ids_without_package.new() as move:
move.product_id = self.productA
move.quantity = 1.0
# with Form(receipt.move_ids_without_package, view='stock.view_stock_move_operations') as form:
# with form.move_line_ids.new() as move_line:
# # move_line.product_id = self.productA
# move_line.location_dest_id = stock_location
# move_line.quantity = 1.0
receipt = receipt_form.save()
# Checks receipt has still its destination location and checks its move
+24 -52
View File
@@ -467,11 +467,9 @@ class TestPacking(TestPackingCommon):
self.env.user.write({'groups_id': [(3, grp_pack.id)]})
self.warehouse.reception_steps = 'two_steps'
# Settings of receipt.
self.warehouse.in_type_id.show_operations = True
self.warehouse.in_type_id.show_entire_packs = True
self.warehouse.in_type_id.show_reserved = True
# Settings of internal transfer.
self.warehouse.int_type_id.show_operations = True
self.warehouse.int_type_id.show_entire_packs = True
self.warehouse.int_type_id.show_reserved = True
@@ -508,17 +506,19 @@ class TestPacking(TestPackingCommon):
receipt.action_confirm()
# Adds quantities then packs them and valids the receipt.
receipt_form = Form(receipt)
with receipt_form.move_line_ids_without_package.edit(0) as move_line:
move_form = Form(receipt.move_ids_without_package[0], view='stock.view_stock_move_operations')
with move_form.move_line_ids.edit(0) as move_line:
move_line.quantity = 1
with receipt_form.move_line_ids_without_package.edit(1) as move_line:
move_form = Form(receipt.move_ids_without_package[1], view='stock.view_stock_move_operations')
with move_form.move_line_ids.edit(0) as move_line:
move_line.quantity = 1
move_form.save()
receipt = receipt_form.save()
receipt.move_ids.picked = True
receipt.action_put_in_pack()
receipt.button_validate()
receipt_package = receipt.package_level_ids_details[0]
receipt_package = receipt.package_level_ids[0]
self.assertEqual(receipt_package.location_dest_id.id, receipt.location_dest_id.id)
self.assertEqual(
receipt_package.move_line_ids[0].location_dest_id.id,
@@ -533,8 +533,8 @@ class TestPacking(TestPackingCommon):
], order='id desc', limit=1)
self.assertEqual(internal_transfer.origin, receipt.name)
self.assertEqual(
len(internal_transfer.package_level_ids_details), 1)
internal_package = internal_transfer.package_level_ids_details[0]
len(internal_transfer.package_level_ids), 1)
internal_package = internal_transfer.package_level_ids[0]
self.assertNotEqual(
internal_package.location_dest_id.id,
internal_transfer.location_dest_id.id)
@@ -553,11 +553,6 @@ class TestPacking(TestPackingCommon):
# Cancels the internal transfer and creates a new one.
internal_transfer.action_cancel()
# @api.depends('picking_type_id.show_operations')
# def _compute_show_operations(self):
# ...
# if self.env.context.get('force_detailed_view'):
# picking.show_operations = True
picking = self.env['stock.picking'].create({
'state': 'draft',
'picking_type_id': self.warehouse.int_type_id.id,
@@ -567,12 +562,12 @@ class TestPacking(TestPackingCommon):
# grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
# self.env.user.write({'groups_id': [(3, grp_multi_loc.id)]})
# Hence, `internal_form.location_id` shouldn't be changed
with internal_form.package_level_ids_details.new() as pack_line:
with internal_form.package_level_ids.new() as pack_line:
pack_line.package_id = receipt_package.package_id
internal_transfer = internal_form.save()
# Checks the package fields have been correctly set.
internal_package = internal_transfer.package_level_ids_details[0]
internal_package = internal_transfer.package_level_ids[0]
self.assertEqual(
internal_package.location_dest_id.id,
internal_transfer.location_dest_id.id)
@@ -611,11 +606,9 @@ class TestPacking(TestPackingCommon):
self.env.user.write({'groups_id': [(3, grp_pack.id)]})
self.warehouse.reception_steps = 'two_steps'
# Settings of receipt.
self.warehouse.in_type_id.show_operations = True
self.warehouse.in_type_id.show_entire_packs = True
self.warehouse.in_type_id.show_reserved = True
# Settings of internal transfer.
self.warehouse.int_type_id.show_operations = True
self.warehouse.int_type_id.show_entire_packs = True
self.warehouse.int_type_id.show_reserved = True
@@ -659,17 +652,19 @@ class TestPacking(TestPackingCommon):
receipt.action_confirm()
# Adds quantities then packs them and valids the receipt.
receipt_form = Form(receipt)
with receipt_form.move_line_ids_without_package.edit(0) as move_line:
move_form = Form(receipt.move_ids_without_package[0], view='stock.view_stock_move_operations')
with move_form.move_line_ids.edit(0) as move_line:
move_line.quantity = 1
with receipt_form.move_line_ids_without_package.edit(1) as move_line:
move_form = Form(receipt.move_ids_without_package[1], view='stock.view_stock_move_operations')
with move_form.move_line_ids.edit(0) as move_line:
move_line.quantity = 1
move_form.save()
receipt = receipt_form.save()
receipt.move_ids.picked = True
receipt.action_put_in_pack()
receipt.button_validate()
receipt_package = receipt.package_level_ids_details[0]
receipt_package = receipt.package_level_ids[0]
self.assertEqual(receipt_package.location_dest_id.id, receipt.location_dest_id.id)
self.assertEqual(
receipt_package.move_line_ids[0].location_dest_id.id,
@@ -684,8 +679,8 @@ class TestPacking(TestPackingCommon):
], order='id desc', limit=1)
self.assertEqual(internal_transfer.origin, receipt.name)
self.assertEqual(
len(internal_transfer.package_level_ids_details), 1)
internal_package = internal_transfer.package_level_ids_details[0]
len(internal_transfer.package_level_ids), 1)
internal_package = internal_transfer.package_level_ids[0]
self.assertEqual(
internal_package.location_dest_id.id,
internal_transfer.location_dest_id.id)
@@ -704,11 +699,6 @@ class TestPacking(TestPackingCommon):
# Cancels the internal transfer and creates a new one.
internal_transfer.action_cancel()
# @api.depends('picking_type_id.show_operations')
# def _compute_show_operations(self):
# ...
# if self.env.context.get('force_detailed_view'):
# picking.show_operations = True
picking = self.env['stock.picking'].create({
'state': 'draft',
'picking_type_id': self.warehouse.int_type_id.id,
@@ -718,12 +708,12 @@ class TestPacking(TestPackingCommon):
# grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
# self.env.user.write({'groups_id': [(3, grp_multi_loc.id)]})
# Hence, `internal_form.location_id` shouldn't be changed
with internal_form.package_level_ids_details.new() as pack_line:
with internal_form.package_level_ids.new() as pack_line:
pack_line.package_id = receipt_package.package_id
internal_transfer = internal_form.save()
# Checks the package fields have been correctly set.
internal_package = internal_transfer.package_level_ids_details[0]
internal_package = internal_transfer.package_level_ids[0]
self.assertEqual(
internal_package.location_dest_id.id,
internal_transfer.location_dest_id.id)
@@ -856,11 +846,6 @@ class TestPacking(TestPackingCommon):
self.warehouse.delivery_steps = 'ship_only'
package = self.env["stock.quant.package"].create({"name": "Src Pack"})
self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 100, package_id=package)
# Required for `package_level_ids_details` to be visible in the view
# <page string="Detailed Operations" invisible="not show_operations">
# <field name="package_level_ids_details"
# invisible="not picking_type_entire_packs or not show_operations"
self.warehouse.out_type_id.show_operations = True
self.warehouse.out_type_id.show_entire_packs = True
picking = self.env['stock.picking'].create({
'location_id': self.stock_location.id,
@@ -875,12 +860,12 @@ class TestPacking(TestPackingCommon):
picking.action_confirm()
picking.action_assign()
with Form(picking) as picking_form:
with picking_form.package_level_ids_details.new() as package_level:
with picking_form.package_level_ids.new() as package_level:
package_level.package_id = package
self.assertEqual(len(picking.move_ids), 1, 'Should have only 1 stock move')
self.assertEqual(len(picking.move_ids), 1, 'Should have only 1 stock move')
with Form(picking) as picking_form:
with picking_form.package_level_ids_details.edit(0) as package_level:
with picking_form.package_level_ids.edit(0) as package_level:
package_level.is_done = True
action = picking.button_validate()
@@ -918,13 +903,8 @@ class TestPacking(TestPackingCommon):
move.product_id = self.productA
move.product_uom_qty = 75
picking.action_assign()
# @api.depends('picking_type_id.show_operations')
# def _compute_show_operations(self):
# ...
# if self.env.context.get('force_detailed_view'):
# picking.show_operations = True
with Form(picking.with_context(force_detailed_view=True)) as picking_form:
with picking_form.package_level_ids_details.new() as package_level:
with picking_form.package_level_ids.new() as package_level:
package_level.package_id = package
with Form(picking) as picking_form:
picking_form.package_level_ids.remove(0)
@@ -1005,18 +985,10 @@ class TestPacking(TestPackingCommon):
moveB.picked = True
picking.action_put_in_pack()
picking.button_validate()
# Required for `package_level_ids_details` to be visible in the view
# <page string="Detailed Operations" invisible="not show_operations">
# <field name="package_level_ids_details"
# invisible="not picking_type_entire_packs or not show_operations"
delivery_type.show_operations = True
delivery_type.show_entire_packs = True
picking, _, _ = create_picking(delivery_type, delivery_type.default_location_src_id, self.customer_location)
packB = picking.package_level_ids[1]
with Form(picking) as picking_form:
with picking_form.package_level_ids_details.edit(0) as package_level:
package_level.is_done = True
picking.package_level_ids_details[0].is_done = True
action_data = picking.button_validate()
backorder_wizard = Form(self.env['stock.backorder.confirmation'].with_context(action_data['context'])).save()
-2
View File
@@ -518,7 +518,6 @@ class TestWarehouse(TestStockCommon):
# Picking Type
self.assertFalse(warehouse.in_type_id.active)
self.assertFalse(warehouse.in_type_id.show_operations)
self.assertFalse(warehouse.out_type_id.active)
self.assertFalse(warehouse.int_type_id.active)
self.assertFalse(warehouse.pick_type_id.active)
@@ -543,7 +542,6 @@ class TestWarehouse(TestStockCommon):
# Picking Type
self.assertTrue(warehouse.in_type_id.active)
self.assertFalse(warehouse.in_type_id.show_operations)
self.assertTrue(warehouse.out_type_id.active)
self.assertTrue(warehouse.int_type_id.active)
self.assertFalse(warehouse.pick_type_id.active)
+17 -10
View File
@@ -77,7 +77,6 @@
<field name="picking_code" column_invisible="True"/>
<field name="product_type" column_invisible="True"/>
<field name="show_details_visible" column_invisible="True"/>
<field name="show_operations" readonly="1" column_invisible="True"/>
<field name="additional" column_invisible="True"/>
<field name="move_lines_count" column_invisible="True"/>
<field name="is_locked" column_invisible="True"/>
@@ -242,24 +241,32 @@
<field name="model">stock.move.line</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" multi_edit="1">
<header>
<button class="btn-primary" name="action_put_in_pack" type="object" string="Put in Pack" groups="stock.group_tracking_lot"/>
</header>
<field name="product_id" context="{'default_detailed_type': 'product'}" required="1" readonly="state == 'done' or move_id"/>
<field name="company_id" column_invisible="True"/>
<field name="move_id" column_invisible="True"/>
<field name="picking_id" column_invisible="True"/>
<field name="picking_code" column_invisible="True"/>
<field name="picking_location_id" column_invisible="True"/>
<field name="picking_location_dest_id" column_invisible="True"/>
<field name="product_uom_category_id" column_invisible="True"/>
<field name="package_id" column_invisible="True"/>
<field name="result_package_id" column_invisible="True"/>
<field name="location_id" column_invisible="True"/>
<field name="location_dest_id" column_invisible="True"/>
<field name="lot_id" groups="stock.group_production_lot" column_invisible="parent.show_lots_text" invisible="not lots_visible" context="{'default_product_id': product_id, 'default_company_id': company_id, 'active_picking_id': picking_id}" optional="show"/>
<field name="lot_name" groups="stock.group_production_lot" column_invisible="not parent.show_lots_text" invisible="not lots_visible" context="{'default_product_id': product_id}"/>
<field name="location_id" options="{'no_create': True}" column_invisible="parent.picking_type_code == 'incoming'" groups="stock.group_stock_multi_locations" domain="[('id', 'child_of', parent.location_id), '|', ('company_id', '=', False), ('company_id', '=', company_id), ('usage', '!=', 'view')]"/>
<field name="location_dest_id" options="{'no_create': True}" column_invisible="parent.picking_type_code == 'outgoing'" groups="stock.group_stock_multi_locations" domain="[('id', 'child_of', parent.location_dest_id), '|', ('company_id', '=', False), ('company_id', '=', company_id), ('usage', '!=', 'view')]"/>
<field name="package_id" groups="stock.group_tracking_lot"/>
<field name="quant_id" column_invisible="context.get('picking_code') == 'incoming'"
domain="[('product_id', '=', product_id), ('location_id', 'child_of', picking_location_id)]"
context="{'default_location_id': location_id, 'default_product_id': product_id, 'search_view_ref': 'stock.quant_search_view', 'tree_view_ref': 'stock.view_stock_quant_tree_simple', 'form_view_ref': 'stock.view_stock_quant_form', 'readonly_form': False}"
widget="pick_from"
options="{'no_open': True}"/>
<field name="lot_id" column_invisible="context.get('show_lots_text')" groups="stock.group_production_lot" invisible="not lots_visible" context="{'default_product_id': product_id, 'default_company_id': company_id, 'active_picking_id': picking_id}" optional="show"/>
<field name="lot_name" column_invisible="not context.get('show_lots_text')" groups="stock.group_production_lot" invisible="not lots_visible" context="{'default_product_id': product_id}"/>
<field name="location_dest_id" options="{'no_create': True}" column_invisible="context.get('picking_code') == 'outgoing'" groups="stock.group_stock_multi_locations" domain="[('id', 'child_of', picking_location_dest_id), '|', ('company_id', '=', False), ('company_id', '=', company_id), ('usage', '!=', 'view')]"/>
<field name="package_id" column_invisible="True"/>
<field name="result_package_id" groups="stock.group_tracking_lot"/>
<field name="lots_visible" column_invisible="True"/>
<field name="owner_id" groups="stock.group_tracking_owner" column_invisible="parent.picking_type_code == 'incoming'"/>
<field name="owner_id" groups="stock.group_tracking_owner" column_invisible="context.get('picking_code') == 'incoming'"/>
<field name="state" column_invisible="True"/>
<field name="is_locked" column_invisible="True"/>
<field name="quantity" readonly="state in ('done', 'cancel') and is_locked" force_save="1"/>
@@ -103,7 +103,6 @@
<field invisible="code not in ['incoming', 'outgoing', 'internal']" name="return_picking_type_id" string="Returns Type"/>
<field name="default_location_return_id" invisible="code not in ['incoming', 'outgoing', 'internal']" groups="stock.group_stock_multi_locations"/>
<field name="create_backorder"/>
<field name="show_operations" invisible="not show_picking_type"/>
</group>
</group>
<group name="second">
+12 -18
View File
@@ -132,7 +132,6 @@
<field name="show_lots_text" invisible="1"/>
<field name="picking_type_code" invisible="1"/>
<field name="hide_picking_type" invisible="1"/>
<field name="show_operations" invisible="1" readonly="1"/>
<field name="show_allocation" invisible="1"/>
<field name="show_reserved" invisible="1" readonly="1"/>
<field name="move_line_exist" invisible="1"/>
@@ -196,12 +195,21 @@
type="object"
help="List view of operations"
groups="base.group_no_one"
invisible="show_operations and (is_locked or state == 'done') or state == 'done' and is_locked"
invisible="(is_locked or state == 'done') or state == 'done' and is_locked"
context="{'picking_type_code': picking_type_code, 'default_picking_id': id, 'form_view_ref':'stock.view_move_form', 'address_in_id': partner_id, 'default_picking_type_id': picking_type_id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id}">
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Operations</span>
</div>
</button>
<button name="action_detailed_operations"
class="oe_stat_button"
icon="fa-bars"
type="object"
help="List view of detailed operations">
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Detailed Operations</span>
</div>
</button>
</div>
<div class="oe_title">
<h1 class="d-flex">
@@ -258,19 +266,6 @@
</group>
<field name="picking_properties" columns="2"/>
<notebook>
<page string="Detailed Operations"
name="detailed_operations"
invisible="not show_operations">
<field name="move_line_ids_without_package"
readonly="not show_operations or state == 'cancel' or (state == 'done' and is_locked)"
context="{'tree_view_ref': 'stock.view_stock_move_line_detailed_operation_tree', 'default_picking_id': id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_company_id': company_id}"/>
<field name="package_level_ids_details"
context="{'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_company_id': company_id}"
invisible="not picking_type_entire_packs or not show_operations"
readonly="state == 'done'" />
<button class="oe_highlight" name="action_put_in_pack" type="object" string="Put in Pack" invisible="state in ('draft', 'done', 'cancel')" groups="stock.group_tracking_lot" data-hotkey="shift+g"/>
</page>
<page string="Operations" name="operations">
<field name="move_ids_without_package" mode="tree,kanban"
widget="stock_move_one2many"
@@ -290,7 +285,6 @@
<field name="picking_code" column_invisible="True"/>
<field name="product_type" column_invisible="True"/>
<field name="show_details_visible" column_invisible="True"/>
<field name="show_operations" readonly="1" column_invisible="True"/>
<field name="show_reserved" column_invisible="True"/>
<field name="additional" column_invisible="True"/>
<field name="move_lines_count" column_invisible="True"/>
@@ -333,7 +327,7 @@
<button name="action_assign_serial" type="object"
icon="fa-plus-square"
role="img" title="Assign Serial Numbers"
invisible="not display_assign_serial or not show_operations"/>
invisible="not display_assign_serial"/>
<button type="object" name="action_product_forecast_report" title="Forecast Report" icon="fa-area-chart"
invisible="quantity == 0 and forecast_availability &lt;= 0 or (parent.picking_type_code == 'outgoing' and state != 'draft')"/>
<button type="object" name="action_product_forecast_report" title="Forecast Report" icon="fa-area-chart text-danger"
@@ -341,7 +335,7 @@
</tree>
</field>
<field name="id" invisible="1"/>
<field name="package_level_ids" context="{'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_company_id': company_id}" invisible="not picking_type_entire_packs or show_operations" readonly="state == 'done'" />
<field name="package_level_ids" context="{'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_company_id': company_id}" invisible="not picking_type_entire_packs" readonly="state == 'done'" />
<button class="btn-secondary float-end" name="action_put_in_pack" type="object" string="Put in Pack" invisible="state in ('draft', 'done', 'cancel')" groups="stock.group_tracking_lot" data-hotkey="shift+g"/>
</page>
<page string="Additional Info" name="extra">
@@ -21,7 +21,6 @@ class TestLifoPrice(ValuationReconciliationTestCommon):
'property_cost_method': 'fifo',
})
res_partner_3 = self.env['res.partner'].create({'name': 'My Test Partner'})
self.company_data['default_warehouse'].out_type_id.show_operations = False
# Set a product as using lifo price
product_form = Form(self.env['product.product'])
@@ -92,8 +91,6 @@ class TestLifoPrice(ValuationReconciliationTestCommon):
purchase_order_lifo2.picking_ids[0].button_validate()
# Let us send some goods
self.company_data['default_warehouse'].out_type_id.show_operations = False
out_form = Form(self.env['stock.picking'])
out_form.picking_type_id = self.company_data['default_warehouse'].out_type_id
with out_form.move_ids_without_package.new() as move: