Add possibility to set a Start Date on Manufacturing Orders. Once the user clicks on Plan, the Work Order are planned at the first time available from this date. When clicking 'Unplan', Work orders are now completely deleted TaskID: 1889399 closes odoo/odoo#30184
627 lines
30 KiB
Python
627 lines
30 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import datetime, timedelta
|
|
import unittest
|
|
from odoo.tests import Form
|
|
from odoo.tests import common
|
|
|
|
|
|
class TestWorkOrderProcess(common.TransactionCase):
|
|
|
|
def setUp(self):
|
|
super(TestWorkOrderProcess, self).setUp()
|
|
self.source_location_id = self.ref('stock.stock_location_14')
|
|
self.warehouse = self.env.ref('stock.warehouse0')
|
|
|
|
def test_00_workorder_process(self):
|
|
""" Testing consume quants and produced quants with workorder """
|
|
|
|
dining_table = self.env.ref("mrp.product_product_computer_desk")
|
|
product_table_sheet = self.env.ref('mrp.product_product_computer_desk_head')
|
|
product_table_leg = self.env.ref('mrp.product_product_computer_desk_leg')
|
|
product_bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
|
|
product_screw = self.env.ref('mrp.product_product_computer_desk_screw')
|
|
self.env['stock.move'].search([('product_id', 'in', [product_bolt.id, product_screw.id])])._do_unreserve()
|
|
(product_bolt + product_screw).write({'type': 'product'})
|
|
|
|
production_table_form = Form(self.env['mrp.production'])
|
|
production_table_form.product_id = dining_table
|
|
production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
|
|
production_table_form.product_qty = 1.0
|
|
production_table_form.product_uom_id = dining_table.uom_id
|
|
production_table = production_table_form.save()
|
|
production_table.action_confirm()
|
|
|
|
# Set tracking lot on finish and consume products.
|
|
dining_table.tracking = 'lot'
|
|
product_table_sheet.tracking = 'lot'
|
|
product_table_leg.tracking = 'lot'
|
|
product_bolt.tracking = "lot"
|
|
|
|
# Initial inventory of product sheet, lags and bolt
|
|
lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
|
|
lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
|
|
lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})
|
|
|
|
# Initialize inventory
|
|
# --------------------
|
|
inventory = self.env['stock.inventory'].create({
|
|
'name': 'Inventory Product Table',
|
|
'filter': 'partial',
|
|
'line_ids': [(0, 0, {
|
|
'product_id': product_table_sheet.id,
|
|
'product_uom_id': product_table_sheet.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_sheet.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_table_leg.id,
|
|
'product_uom_id': product_table_leg.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_leg.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_bolt.id,
|
|
'product_uom_id': product_bolt.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_bolt.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_screw.id,
|
|
'product_uom_id': product_screw.uom_id.id,
|
|
'product_qty': 20,
|
|
'location_id': self.source_location_id
|
|
})]
|
|
})
|
|
inventory.action_validate()
|
|
|
|
# Create work order
|
|
production_table.button_plan()
|
|
# Check Work order created or not
|
|
self.assertEqual(len(production_table.workorder_ids), 1)
|
|
|
|
# ---------------------------------------------------------
|
|
# Process all workorder and check it state.
|
|
# ----------------------------------------------------------
|
|
|
|
workorder = production_table.workorder_ids[0]
|
|
self.assertEqual(workorder.state, 'ready', "workorder state should be ready.")
|
|
|
|
# --------------------------------------------------------------
|
|
# Process assembly line
|
|
# ---------------------------------------------------------
|
|
finished_lot =self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
|
|
workorder.write({'final_lot_id': finished_lot.id})
|
|
workorder.button_start()
|
|
for active_move_line_id in workorder.active_move_line_ids:
|
|
if active_move_line_id.product_id.id == product_bolt.id:
|
|
active_move_line_id.write({'lot_id': lot_bolt.id, 'qty_done': 1})
|
|
if active_move_line_id.product_id.id == product_table_sheet.id:
|
|
active_move_line_id.write({'lot_id': lot_sheet.id, 'qty_done': 1})
|
|
if active_move_line_id.product_id.id == product_table_leg.id:
|
|
active_move_line_id.write({'lot_id': lot_leg.id, 'qty_done': 1})
|
|
self.assertEqual(workorder.state, 'progress')
|
|
workorder.record_production()
|
|
self.assertEqual(workorder.state, 'done')
|
|
move_table_sheet = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_sheet)
|
|
self.assertEqual(move_table_sheet.quantity_done, 1)
|
|
|
|
# ---------------------------------------------------------------
|
|
# Check consume quants and produce quants after posting inventory
|
|
# ---------------------------------------------------------------
|
|
production_table.button_mark_done()
|
|
|
|
self.assertEqual(product_screw.qty_available, 10)
|
|
self.assertEqual(product_bolt.qty_available, 19)
|
|
self.assertEqual(product_table_leg.qty_available, 19)
|
|
self.assertEqual(product_table_sheet.qty_available, 19)
|
|
|
|
def test_00b_workorder_process(self):
|
|
""" Testing consume quants and produced quants with workorder """
|
|
dining_table = self.env.ref("mrp.product_product_computer_desk")
|
|
product_table_sheet = self.env.ref('mrp.product_product_computer_desk_head')
|
|
product_table_leg = self.env.ref('mrp.product_product_computer_desk_leg')
|
|
product_bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
|
|
self.env['stock.move'].search([('product_id', '=', product_bolt.id)])._do_unreserve()
|
|
product_bolt.type = 'product'
|
|
|
|
bom = self.env['mrp.bom'].browse(self.ref("mrp.mrp_bom_desk"))
|
|
bom.routing_id = self.ref('mrp.mrp_routing_1')
|
|
|
|
bom.bom_line_ids.filtered(lambda p: p.product_id == product_table_sheet).operation_id = bom.routing_id.operation_ids[0]
|
|
bom.bom_line_ids.filtered(lambda p: p.product_id == product_table_leg).operation_id = bom.routing_id.operation_ids[1]
|
|
bom.bom_line_ids.filtered(lambda p: p.product_id == product_bolt).operation_id = bom.routing_id.operation_ids[2]
|
|
|
|
production_table_form = Form(self.env['mrp.production'])
|
|
production_table_form.product_id = dining_table
|
|
production_table_form.bom_id = bom
|
|
production_table_form.product_qty = 2.0
|
|
production_table_form.product_uom_id = dining_table.uom_id
|
|
production_table = production_table_form.save()
|
|
# Set tracking lot on finish and consume products.
|
|
dining_table.tracking = 'lot'
|
|
product_table_sheet.tracking = 'lot'
|
|
product_table_leg.tracking = 'lot'
|
|
product_bolt.tracking = "lot"
|
|
production_table.action_confirm()
|
|
# Initial inventory of product sheet, lags and bolt
|
|
lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
|
|
lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
|
|
lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})
|
|
|
|
# Initialize inventory
|
|
# --------------------
|
|
inventory = self.env['stock.inventory'].create({
|
|
'name': 'Inventory Product Table',
|
|
'filter': 'partial',
|
|
'line_ids': [(0, 0, {
|
|
'product_id': product_table_sheet.id,
|
|
'product_uom_id': product_table_sheet.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_sheet.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_table_leg.id,
|
|
'product_uom_id': product_table_leg.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_leg.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_bolt.id,
|
|
'product_uom_id': product_bolt.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_bolt.id,
|
|
'location_id': self.source_location_id
|
|
})]
|
|
})
|
|
inventory.action_validate()
|
|
|
|
# Create work order
|
|
production_table.button_plan()
|
|
# Check Work order created or not
|
|
self.assertEqual(len(production_table.workorder_ids), 3)
|
|
|
|
# ---------------------------------------------------------
|
|
# Process all workorder and check it state.
|
|
# ----------------------------------------------------------
|
|
|
|
workorders = production_table.workorder_ids
|
|
self.assertEqual(workorders[0].state, 'ready', "First workorder state should be ready.")
|
|
self.assertEqual(workorders[1].state, 'pending')
|
|
self.assertEqual(workorders[2].state, 'pending')
|
|
|
|
# --------------------------------------------------------------
|
|
# Process cutting operation...
|
|
# ---------------------------------------------------------
|
|
finished_lot = self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
|
|
workorders[0].write({'final_lot_id': finished_lot.id, 'qty_producing': 1.0})
|
|
workorders[0].button_start()
|
|
workorders[0].active_move_line_ids[0].write({'lot_id': lot_sheet.id, 'qty_done': 1})
|
|
self.assertEqual(workorders[0].state, 'progress')
|
|
workorders[0].record_production()
|
|
|
|
move_table_sheet = production_table.move_raw_ids.filtered(lambda p: p.product_id == product_table_sheet)
|
|
self.assertEqual(move_table_sheet.quantity_done, 1)
|
|
|
|
# --------------------------------------------------------------
|
|
# Process drilling operation ...
|
|
# ---------------------------------------------------------
|
|
workorders[1].button_start()
|
|
workorders[1].qty_producing = 1.0
|
|
workorders[1].active_move_line_ids[0].write({'lot_id': lot_leg.id, 'qty_done': 4})
|
|
workorders[1].record_production()
|
|
move_leg = production_table.move_raw_ids.filtered(lambda p: p.product_id == product_table_leg)
|
|
#self.assertEqual(workorders[1].state, 'done')
|
|
self.assertEqual(move_leg.quantity_done, 4)
|
|
|
|
# --------------------------------------------------------------
|
|
# Process fitting operation ...
|
|
# ---------------------------------------------------------
|
|
workorders[2].button_start()
|
|
workorders[2].qty_producing = 1.0
|
|
move_lot = workorders[2].active_move_line_ids[0]
|
|
move_lot.write({'lot_id': lot_bolt.id, 'qty_done': 4})
|
|
move_table_bolt = production_table.move_raw_ids.filtered(lambda p: p.product_id.id == product_bolt.id)
|
|
workorders[2].record_production()
|
|
self.assertEqual(move_table_bolt.quantity_done, 4)
|
|
|
|
# Change the quantity of the production order to 1
|
|
wiz = self.env['change.production.qty'].create({'mo_id': production_table.id ,
|
|
'product_qty': 1.0})
|
|
wiz.change_prod_qty()
|
|
# ---------------------------------------------------------------
|
|
# Check consume quants and produce quants after posting inventory
|
|
# ---------------------------------------------------------------
|
|
production_table.post_inventory()
|
|
self.assertEqual(sum(move_table_sheet.mapped('quantity_done')), 1, "Wrong quantity of consumed product %s" % move_table_sheet.product_id.name)
|
|
self.assertEqual(sum(move_leg.mapped('quantity_done')), 4, "Wrong quantity of consumed product %s" % move_leg.product_id.name)
|
|
self.assertEqual(sum(move_table_bolt.mapped('quantity_done')), 4, "Wrong quantity of consumed product %s" % move_table_bolt.product_id.name)
|
|
|
|
def test_01_without_workorder(self):
|
|
""" Testing consume quants and produced quants without workorder """
|
|
unit = self.ref("uom.product_uom_unit")
|
|
custom_laptop = self.env.ref("product.product_product_27")
|
|
custom_laptop.tracking = 'lot'
|
|
|
|
# Create new product charger and keybord
|
|
# --------------------------------------
|
|
product_charger = self.env['product.product'].create({
|
|
'name': 'Charger',
|
|
'type': 'product',
|
|
'tracking': 'lot',
|
|
'uom_id': unit,
|
|
'uom_po_id': unit})
|
|
product_keybord = self.env['product.product'].create({
|
|
'name': 'Usb Keybord',
|
|
'type': 'product',
|
|
'tracking': 'lot',
|
|
'uom_id': unit,
|
|
'uom_po_id': unit})
|
|
|
|
# Create bill of material for customized laptop.
|
|
|
|
bom_custom_laptop = self.env['mrp.bom'].create({
|
|
'product_tmpl_id': custom_laptop.product_tmpl_id.id,
|
|
'product_qty': 10,
|
|
'product_uom_id': unit,
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': product_charger.id,
|
|
'product_qty': 20,
|
|
'product_uom_id': unit
|
|
}), (0, 0, {
|
|
'product_id': product_keybord.id,
|
|
'product_qty': 20,
|
|
'product_uom_id': unit
|
|
})]
|
|
})
|
|
|
|
# Create production order for customize laptop.
|
|
|
|
mo_custom_laptop_form = Form(self.env['mrp.production'])
|
|
mo_custom_laptop_form.product_id = custom_laptop
|
|
mo_custom_laptop_form.bom_id = bom_custom_laptop
|
|
mo_custom_laptop_form.product_qty = 10.0
|
|
mo_custom_laptop_form.product_uom_id = self.env.ref("uom.product_uom_unit")
|
|
mo_custom_laptop = mo_custom_laptop_form.save()
|
|
|
|
mo_custom_laptop.action_confirm()
|
|
# Assign component to production order.
|
|
mo_custom_laptop.action_assign()
|
|
|
|
# Check production order status of availablity
|
|
|
|
self.assertEqual(mo_custom_laptop.reservation_state, 'confirmed')
|
|
|
|
# --------------------------------------------------
|
|
# Set inventory for rawmaterial charger and keybord
|
|
# --------------------------------------------------
|
|
|
|
lot_charger = self.env['stock.production.lot'].create({'product_id': product_charger.id})
|
|
lot_keybord = self.env['stock.production.lot'].create({'product_id': product_keybord.id})
|
|
|
|
# Initialize Inventory
|
|
# --------------------
|
|
inventory = self.env['stock.inventory'].create({
|
|
'name': 'Inventory Product Table',
|
|
'filter': 'partial',
|
|
'line_ids': [(0, 0, {
|
|
'product_id': product_charger.id,
|
|
'product_uom_id': product_charger.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_charger.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_keybord.id,
|
|
'product_uom_id': product_keybord.uom_id.id,
|
|
'product_qty': 20,
|
|
'prod_lot_id': lot_keybord.id,
|
|
'location_id': self.source_location_id
|
|
})]
|
|
})
|
|
# inventory.action_start()
|
|
inventory.action_validate()
|
|
|
|
# Check consumed move status
|
|
mo_custom_laptop.action_assign()
|
|
self.assertEqual(mo_custom_laptop.reservation_state, 'assigned')
|
|
|
|
# Check current status of raw materials.
|
|
for move in mo_custom_laptop.move_raw_ids:
|
|
self.assertEqual(move.product_uom_qty, 20, "Wrong consume quantity of raw material %s: %s instead of %s" % (move.product_id.name, move.product_uom_qty, 20))
|
|
self.assertEqual(move.quantity_done, 0, "Wrong produced quantity on raw material %s: %s instead of %s" % (move.product_id.name, move.quantity_done, 0))
|
|
|
|
# -----------------
|
|
# Start production
|
|
# -----------------
|
|
|
|
# Produce 6 Unit of custom laptop will consume ( 12 Unit of keybord and 12 Unit of charger)
|
|
context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id}
|
|
product_form = Form(self.env['mrp.product.produce'].with_context(context))
|
|
product_form.product_qty = 6.00
|
|
laptop_lot_001 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
|
|
product_form.lot_id = laptop_lot_001
|
|
product_consume = product_form.save()
|
|
product_consume.produce_line_ids[0].qty_done = 12
|
|
product_consume.do_produce()
|
|
|
|
# Check consumed move after produce 6 quantity of customized laptop.
|
|
for move in mo_custom_laptop.move_raw_ids:
|
|
self.assertEqual(move.quantity_done, 12, "Wrong produced quantity on raw material %s" % (move.product_id.name))
|
|
self.assertEqual(len(mo_custom_laptop.move_raw_ids), 2)
|
|
mo_custom_laptop.post_inventory()
|
|
self.assertEqual(len(mo_custom_laptop.move_raw_ids), 4)
|
|
|
|
# Check done move and confirmed move quantity.
|
|
|
|
charger_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state == 'done')
|
|
keybord_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state == 'done')
|
|
self.assertEquals(charger_done_move.product_uom_qty, 12)
|
|
self.assertEquals(keybord_done_move.product_uom_qty, 12)
|
|
|
|
# Produce remaining 4 quantity
|
|
# ----------------------------
|
|
|
|
# Produce 4 Unit of custom laptop will consume ( 8 Unit of keybord and 8 Unit of charger).
|
|
context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id}
|
|
produce_form = Form(self.env['mrp.product.produce'].with_context(context))
|
|
produce_form.product_qty = 4.00
|
|
laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
|
|
produce_form.lot_id = laptop_lot_002
|
|
product_consume = produce_form.save()
|
|
self.assertEquals(len(product_consume.produce_line_ids), 2)
|
|
product_consume.produce_line_ids[0].qty_done = 8
|
|
product_consume.do_produce()
|
|
charger_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state != 'done')
|
|
keybord_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state !='done')
|
|
self.assertEquals(charger_move.quantity_done, 8, "Wrong consumed quantity of %s" % charger_move.product_id.name)
|
|
self.assertEquals(keybord_move.quantity_done, 8, "Wrong consumed quantity of %s" % keybord_move.product_id.name)
|
|
|
|
# Post Inventory of production order.
|
|
mo_custom_laptop.post_inventory()
|
|
|
|
# raw_moves_state = any(move.state != 'done' for move in mo_custom_laptop.move_raw_ids)
|
|
# finsh_moves_state = any(move.state != 'done' for move in mo_custom_laptop.move_finished_ids)
|
|
# self.assertFalse(raw_moves_state, "Wrong state in consumed moves of production order.")
|
|
# self.assertFalse(finsh_moves_state, "Wrong state in consumed moves of production order.")
|
|
#
|
|
# # Finished move quants of production order
|
|
#
|
|
# finshed_quant_lot_001 = mo_custom_laptop.move_finished_ids.filtered(lambda x: x.product_id.id == custom_laptop.id and x.product_uom_qty==6).mapped('quant_ids')
|
|
# finshed_quant_lot_002 = mo_custom_laptop.move_finished_ids.filtered(lambda x: x.product_id.id == custom_laptop.id and x.product_uom_qty==4).mapped('quant_ids')
|
|
#
|
|
# # Check total quantity consumed of charger, keybord
|
|
# # --------------------------------------------------
|
|
# charger_quants = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state == 'done').mapped('quant_ids')
|
|
# keybord_moves = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state == 'done').mapped('quant_ids')
|
|
# self.assertEqual(sum(charger_quants.mapped('qty')), 20)
|
|
# self.assertEqual(sum(keybord_moves.mapped('qty')), 20)
|
|
|
|
def test_02_different_uom_on_bomlines(self):
|
|
""" Testing bill of material with different unit of measure."""
|
|
route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
|
|
route_mto = self.warehouse.mto_pull_id.route_id.id
|
|
unit = self.ref("uom.product_uom_unit")
|
|
dozen = self.ref("uom.product_uom_dozen")
|
|
kg = self.ref("uom.product_uom_kgm")
|
|
gm = self.ref("uom.product_uom_gram")
|
|
# Create Product A, B, C
|
|
product_A = self.env['product.product'].create({
|
|
'name': 'Product A',
|
|
'type': 'product',
|
|
'tracking': 'lot',
|
|
'uom_id': dozen,
|
|
'uom_po_id': dozen,
|
|
'route_ids': [(6, 0, [route_manufacture, route_mto])]})
|
|
product_B = self.env['product.product'].create({
|
|
'name': 'Product B',
|
|
'type': 'product',
|
|
'tracking': 'lot',
|
|
'uom_id': dozen,
|
|
'uom_po_id': dozen})
|
|
product_C = self.env['product.product'].create({
|
|
'name': 'Product C',
|
|
'type': 'product',
|
|
'tracking': 'lot',
|
|
'uom_id': kg,
|
|
'uom_po_id': kg})
|
|
|
|
# Bill of materials
|
|
# -----------------
|
|
|
|
#===================================
|
|
# Product A 1 Unit
|
|
# Product B 4 Unit
|
|
# Product C 600 gram
|
|
# -----------------------------------
|
|
|
|
bom_a = self.env['mrp.bom'].create({
|
|
'product_tmpl_id': product_A.product_tmpl_id.id,
|
|
'product_qty': 2,
|
|
'product_uom_id': unit,
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': product_B.id,
|
|
'product_qty': 4,
|
|
'product_uom_id': unit
|
|
}), (0, 0, {
|
|
'product_id': product_C.id,
|
|
'product_qty': 600,
|
|
'product_uom_id': gm
|
|
})]
|
|
})
|
|
|
|
# Create production order with product A 10 Unit.
|
|
# -----------------------------------------------
|
|
|
|
mo_custom_product_form = Form(self.env['mrp.production'])
|
|
mo_custom_product_form.product_id = product_A
|
|
mo_custom_product_form.bom_id = bom_a
|
|
mo_custom_product_form.product_qty = 10.0
|
|
mo_custom_product_form.product_uom_id = self.env.ref("uom.product_uom_unit")
|
|
mo_custom_product = mo_custom_product_form.save()
|
|
|
|
move_product_b = mo_custom_product.move_raw_ids.filtered(lambda x: x.product_id == product_B)
|
|
move_product_c = mo_custom_product.move_raw_ids.filtered(lambda x: x.product_id == product_C)
|
|
|
|
# Check move correctly created or not.
|
|
self.assertEqual(move_product_b.product_uom_qty, 20)
|
|
self.assertEqual(move_product_b.product_uom.id, unit)
|
|
self.assertEqual(move_product_c.product_uom_qty, 3000)
|
|
self.assertEqual(move_product_c.product_uom.id, gm)
|
|
|
|
# Lot create for product B and product C
|
|
# ---------------------------------------
|
|
lot_a = self.env['stock.production.lot'].create({'product_id': product_A.id})
|
|
lot_b = self.env['stock.production.lot'].create({'product_id': product_B.id})
|
|
lot_c = self.env['stock.production.lot'].create({'product_id': product_C.id})
|
|
|
|
# Inventory Update
|
|
# ----------------
|
|
inventory = self.env['stock.inventory'].create({
|
|
'name': 'Inventory Product B and C',
|
|
'filter': 'partial',
|
|
'line_ids': [(0, 0, {
|
|
'product_id': product_B.id,
|
|
'product_uom_id': product_B.uom_id.id,
|
|
'product_qty': 3,
|
|
'prod_lot_id': lot_b.id,
|
|
'location_id': self.source_location_id
|
|
}), (0, 0, {
|
|
'product_id': product_C.id,
|
|
'product_uom_id': product_C.uom_id.id,
|
|
'product_qty': 3,
|
|
'prod_lot_id': lot_c.id,
|
|
'location_id': self.source_location_id
|
|
})]
|
|
})
|
|
# inventory.action_start()
|
|
inventory.action_validate()
|
|
|
|
# Start Production ...
|
|
# --------------------
|
|
|
|
mo_custom_product.action_confirm()
|
|
mo_custom_product.action_assign()
|
|
context = {"active_ids": [mo_custom_product.id], "active_id": mo_custom_product.id}
|
|
produce_form = Form(self.env['mrp.product.produce'].with_context(context))
|
|
produce_form.product_qty = 10.00
|
|
produce_form.lot_id = lot_a
|
|
product_consume = produce_form.save()
|
|
# laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
|
|
self.assertEquals(len(product_consume.produce_line_ids), 2)
|
|
product_consume.produce_line_ids.filtered(lambda x : x.product_id == product_C).write({'qty_done': 3000})
|
|
product_consume.produce_line_ids.filtered(lambda x : x.product_id == product_B).write({'qty_done': 20})
|
|
product_consume.do_produce()
|
|
mo_custom_product.post_inventory()
|
|
|
|
# Check correct quant linked with move or not
|
|
# -------------------------------------------
|
|
#TODO: check original quants qtys diminished
|
|
# self.assertEqual(len(move_product_b.quant_ids), 1)
|
|
# self.assertEqual(len(move_product_c.quant_ids), 1)
|
|
# self.assertEqual(move_product_b.quant_ids.qty, move_product_b.product_qty)
|
|
# self.assertEqual(move_product_c.quant_ids.qty, 3)
|
|
# self.assertEqual(move_product_c.quant_ids.product_uom_id.id, kg)
|
|
|
|
def test_03_test_serial_number_defaults(self):
|
|
""" Test that the correct serial number is suggested on consecutive work orders. """
|
|
laptop = self.env.ref("product.product_product_25")
|
|
graphics_card = self.env.ref("product.product_product_24")
|
|
unit = self.env.ref("uom.product_uom_unit")
|
|
three_step_routing = self.env.ref("mrp.mrp_routing_1")
|
|
|
|
laptop.tracking = 'serial'
|
|
|
|
bom_laptop = self.env['mrp.bom'].create({
|
|
'product_tmpl_id': laptop.product_tmpl_id.id,
|
|
'product_qty': 1,
|
|
'product_uom_id': unit.id,
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': graphics_card.id,
|
|
'product_qty': 1,
|
|
'product_uom_id': unit.id
|
|
})],
|
|
'routing_id': three_step_routing.id
|
|
})
|
|
|
|
mo_laptop_form = Form(self.env['mrp.production'])
|
|
mo_laptop_form.product_id = laptop
|
|
mo_laptop_form.bom_id = bom_laptop
|
|
mo_laptop_form.product_qty = 3
|
|
mo_laptop = mo_laptop_form.save()
|
|
|
|
mo_laptop.action_confirm()
|
|
mo_laptop.button_plan()
|
|
workorders = mo_laptop.workorder_ids
|
|
self.assertEqual(len(workorders), 3)
|
|
|
|
workorders[0].button_start()
|
|
serial_a = self.env['stock.production.lot'].create({'product_id': laptop.id})
|
|
workorders[0].final_lot_id = serial_a
|
|
workorders[0].record_production()
|
|
serial_b = self.env['stock.production.lot'].create({'product_id': laptop.id})
|
|
workorders[0].final_lot_id = serial_b
|
|
workorders[0].record_production()
|
|
serial_c = self.env['stock.production.lot'].create({'product_id': laptop.id})
|
|
workorders[0].final_lot_id = serial_c
|
|
workorders[0].record_production()
|
|
self.assertEqual(workorders[0].state, 'done')
|
|
|
|
for workorder in workorders - workorders[0]:
|
|
self.assertEqual(workorder.final_lot_id, serial_a)
|
|
workorder.record_production()
|
|
self.assertEqual(workorder.final_lot_id, serial_b)
|
|
workorder.record_production()
|
|
self.assertEqual(workorder.final_lot_id, serial_c)
|
|
workorder.record_production()
|
|
self.assertEqual(workorder.state, 'done')
|
|
|
|
def test_04_test_planning_date(self):
|
|
""" Test that workorder are planned at the correct time. """
|
|
# Remove attendances linked to the calendar, this means that the workcenter is working 24/7
|
|
self.env['resource.calendar'].search([]).write({'attendance_ids': [(5, False, False)]})
|
|
|
|
dining_table = self.env.ref("mrp.product_product_computer_desk")
|
|
|
|
production_table_form = Form(self.env['mrp.production'])
|
|
production_table_form.product_id = dining_table
|
|
production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
|
|
production_table_form.product_qty = 1.0
|
|
production_table_form.product_uom_id = dining_table.uom_id
|
|
production_table = production_table_form.save()
|
|
production_table.action_confirm()
|
|
|
|
# Create work order
|
|
production_table.button_plan()
|
|
workorder = production_table.workorder_ids[0]
|
|
|
|
# Check that the workorder is planned now and that it lasts one hour
|
|
self.assertAlmostEqual(workorder.date_planned_start, datetime.now(), delta=timedelta(seconds=10), msg="Workorder should be planned now.")
|
|
self.assertAlmostEqual(workorder.date_planned_finished, datetime.now() + timedelta(hours=1), delta=timedelta(seconds=10), msg="Workorder should be done in an hour.")
|
|
|
|
def test_04b_test_planning_date(self):
|
|
""" Test that workorder are planned at the correct time when setting a start date """
|
|
# Remove attendances linked to the calendar, this means that the workcenter is working 24/7
|
|
self.env['resource.calendar'].search([]).write({'attendance_ids': [(5, False, False)]})
|
|
|
|
dining_table = self.env.ref("mrp.product_product_computer_desk")
|
|
|
|
date_start = datetime.now() + timedelta(days=1)
|
|
|
|
production_table_form = Form(self.env['mrp.production'])
|
|
production_table_form.product_id = dining_table
|
|
production_table_form.bom_id = self.env.ref("mrp.mrp_bom_desk")
|
|
production_table_form.product_qty = 1.0
|
|
production_table_form.product_uom_id = dining_table.uom_id
|
|
production_table_form.date_start_wo = date_start
|
|
production_table = production_table_form.save()
|
|
production_table.action_confirm()
|
|
|
|
# Create work order
|
|
production_table.button_plan()
|
|
workorder = production_table.workorder_ids[0]
|
|
|
|
# Check that the workorder is planned now and that it lasts one hour
|
|
self.assertEqual(workorder.date_planned_start, date_start, msg="Workorder should be planned tomorrow.")
|
|
self.assertEqual(workorder.date_planned_finished, date_start + timedelta(hours=1), msg="Workorder should be done one hour later.")
|