mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 15:32:04 +02:00
19.0 vanilla
This commit is contained in:
parent
79f83631d5
commit
73afc09215
6267 changed files with 1534193 additions and 1130106 deletions
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_generate_serial_numbers
|
||||
from . import test_stock_lot
|
||||
|
|
|
|||
|
|
@ -0,0 +1,281 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import datetime
|
||||
from freezegun import freeze_time
|
||||
|
||||
from odoo import Command
|
||||
from odoo.addons.stock.tests.test_generate_serial_numbers import StockGenerateCommon
|
||||
from odoo.addons.stock.tests.test_picking_tours import TestStockPickingTour
|
||||
from odoo.tools.misc import get_lang
|
||||
|
||||
|
||||
class TestStockLot(StockGenerateCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.product_lot = cls.env['product.product'].create({
|
||||
'name': 'Tracked by Lot Numbers',
|
||||
'tracking': 'lot',
|
||||
'is_storable': True,
|
||||
'use_expiration_date': True,
|
||||
})
|
||||
|
||||
def _import_lots(self, lots, move):
|
||||
location_id = move.location_id
|
||||
move_lines_vals = move.split_lots(lots)
|
||||
move_lines_commands = move._generate_serial_move_line_commands(move_lines_vals, location_dest_id=location_id)
|
||||
move.update({'move_line_ids': move_lines_commands})
|
||||
|
||||
def test_set_multiple_lot_name_with_expiration_date_01(self):
|
||||
""" In a move line's `lot_name` field, pastes a list of lots and expiration dates.
|
||||
Checks the values are correctly interpreted and the expiration dates are correctly created
|
||||
depending of the user lang's date format.
|
||||
"""
|
||||
user_lang = self.env['res.lang'].browse([get_lang(self.env).id])
|
||||
# Try first with the "day/month/year" date format.
|
||||
user_lang.date_format = "%d/%m/%y"
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "03/05/25", "datetime": datetime.strptime('2025-05-03', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "06/05/25", "datetime": datetime.strptime('2025-05-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "03/06/25", "datetime": datetime.strptime('2025-06-03', "%Y-%m-%d")},
|
||||
{'lot_name': "ln04", "date": "06/06/25", "datetime": datetime.strptime('2025-06-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln05", "date": "03/07/25", "datetime": datetime.strptime('2025-07-03', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, list_lot_and_qty[i]["datetime"])
|
||||
|
||||
# Same test but with with the "month/day/year" date format this time.
|
||||
user_lang.date_format = "%m/%d/%y"
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "03/05/25", "datetime": datetime.strptime('2025-03-05', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "06/05/25", "datetime": datetime.strptime('2025-06-05', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "03/06/25", "datetime": datetime.strptime('2025-03-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln04", "date": "06/06/25", "datetime": datetime.strptime('2025-06-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln05", "date": "03/07/25", "datetime": datetime.strptime('2025-03-07', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, list_lot_and_qty[i]["datetime"])
|
||||
|
||||
def test_set_multiple_lot_name_with_expiration_date_02_product_dont_use_expiration_date(self):
|
||||
""" In a move line's `lot_name` field, pastes a list of lots and expiration dates.
|
||||
Checks the values are correctly interpreted and since the product doesn't use expiration
|
||||
date, the expiration dates should be ignored.
|
||||
"""
|
||||
self.product_lot.use_expiration_date = False
|
||||
user_lang = self.env['res.lang'].browse([get_lang(self.env).id])
|
||||
# Try first with the "day/month/year" date format.
|
||||
user_lang.date_format = "%d/%m/%y"
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "03/05/25", "datetime": datetime.strptime('2025-05-03', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "06/05/25", "datetime": datetime.strptime('2025-05-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "03/06/25", "datetime": datetime.strptime('2025-06-03', "%Y-%m-%d")},
|
||||
{'lot_name': "ln04", "date": "06/06/25", "datetime": datetime.strptime('2025-06-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln05", "date": "03/07/25", "datetime": datetime.strptime('2025-07-03', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, False)
|
||||
|
||||
def test_set_multiple_lot_name_with_expiration_date_03_adaptive_date_format(self):
|
||||
""" Checks if the given dates don't follow the user lang's date format, the created expiration
|
||||
date will follow the first given date's format (at least in the scope of the limitations).
|
||||
"""
|
||||
user_lang = self.env['res.lang'].browse([get_lang(self.env).id])
|
||||
# Month first in the system but day in the first place in the given dates.
|
||||
user_lang.date_format = "%m/%d/%y"
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "30/05/25", "datetime": datetime.strptime('2025-05-30', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "06/05/25", "datetime": datetime.strptime('2025-05-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "01/06/25", "datetime": datetime.strptime('2025-06-01', "%Y-%m-%d")},
|
||||
{'lot_name': "ln04", "date": "06/06/25", "datetime": datetime.strptime('2025-06-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln05", "date": "01/07/25", "datetime": datetime.strptime('2025-07-01', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, list_lot_and_qty[i]["datetime"])
|
||||
|
||||
# Now, tries with day first but the year is at the first place in the given dates.
|
||||
user_lang.date_format = "%d/%m/%y"
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "89/05/04", "datetime": datetime.strptime('1989-05-04', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "10/05/06", "datetime": datetime.strptime('2010-05-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "12/06/15", "datetime": datetime.strptime('2012-06-15', "%Y-%m-%d")},
|
||||
{'lot_name': "ln04", "date": "30/06/06", "datetime": datetime.strptime('2030-06-06', "%Y-%m-%d")},
|
||||
{'lot_name': "ln05", "date": "04/07/08", "datetime": datetime.strptime('2004-07-08', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, list_lot_and_qty[i]["datetime"])
|
||||
|
||||
def test_set_multiple_lot_name_with_expiration_date_04_written_months(self):
|
||||
""" Checks the expiration date is correctly created when the month is written in letters.
|
||||
"""
|
||||
list_lot_and_qty = [
|
||||
{'lot_name': "ln01", "date": "01 march 2077", "datetime": datetime.strptime('2077-03-01', "%Y-%m-%d")},
|
||||
{'lot_name': "ln02", "date": "11 april 2077", "datetime": datetime.strptime('2077-04-11', "%Y-%m-%d")},
|
||||
{'lot_name': "ln03", "date": "10 december 2077", "datetime": datetime.strptime('2077-12-10', "%Y-%m-%d")},
|
||||
]
|
||||
list_as_string = '\n'.join([f'{line["lot_name"]};{line["date"]}' for line in list_lot_and_qty])
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
for i, move_line in enumerate(move.move_line_ids):
|
||||
self.assertEqual(move_line.lot_name, list_lot_and_qty[i]['lot_name'])
|
||||
self.assertEqual(move_line.quantity, 1)
|
||||
self.assertEqual(move_line.expiration_date, list_lot_and_qty[i]["datetime"])
|
||||
|
||||
@freeze_time('2025-9-13')
|
||||
def test_set_multiple_lot_name_with_expiration_date_05_import_dates(self):
|
||||
""" When importing lot names, quantities and expiration dates, make sure the date is not
|
||||
replaced by the computed date and if there's no date, it takes the computed date. """
|
||||
self.product_lot.expiration_time = 10
|
||||
receipt_picking = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.warehouse.in_type_id.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.warehouse.lot_stock_id.id,
|
||||
'state': 'draft',
|
||||
'move_ids': [Command.create({
|
||||
'product_id': self.product_lot.id,
|
||||
'product_uom_qty': 20,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.warehouse.lot_stock_id.id,
|
||||
})]
|
||||
})
|
||||
action_context = {
|
||||
'default_company_id': self.env.company.id,
|
||||
'default_picking_id': receipt_picking.id,
|
||||
'default_picking_type_id': self.warehouse.in_type_id.id,
|
||||
'default_location_id': receipt_picking.location_id.id,
|
||||
'default_location_dest_id': receipt_picking.location_dest_id.id,
|
||||
'default_product_id': self.product_lot.id,
|
||||
'default_tracking': 'lot',
|
||||
}
|
||||
move_line_vals = self.env['stock.move'].action_generate_lot_line_vals(
|
||||
action_context, 'import', None, 0, 'lot1;10;2025-12-31\nlot2;7\nlot3;3;1970-1-1'
|
||||
)
|
||||
self.assert_move_line_vals_values(move_line_vals, [
|
||||
{'quantity': 10, 'lot_name': 'lot1', 'expiration_date': datetime.strptime('2025-12-31', "%Y-%m-%d")},
|
||||
{'quantity': 7, 'lot_name': 'lot2', 'expiration_date': datetime.strptime('2025-9-23', "%Y-%m-%d")},
|
||||
{'quantity': 3, 'lot_name': 'lot3', 'expiration_date': datetime.strptime('1970-1-1', "%Y-%m-%d")},
|
||||
])
|
||||
|
||||
@freeze_time('2023-04-17')
|
||||
def test_set_multiple_lot_name_with_expiration_date_05_wrong_given_date(self):
|
||||
""" This test ensure when the given dates aren't correctly written, the
|
||||
full string is used as the lot's name.
|
||||
"""
|
||||
today = datetime(day=17, month=4, year=2023)
|
||||
list_lot_and_qty = [
|
||||
"ln01\t31/12", # Day is missing but the date is valid.
|
||||
"ln02\t1989-04", # Day is missing but the date is valid.
|
||||
"ln03\t01", # Single number: will be used as the quantity.
|
||||
"ln04\t1989", # Single number: will be used as the quantity.
|
||||
"ln05\t1989.04", # Signle number (with decimal): will be used as the quantity.
|
||||
"ln06\t1989+04", # Wrong, all the string will be used as the lot name.
|
||||
"ln07\tdacember", # Typo, all the string will be used as the lot name.
|
||||
"ln08\tdecember", # Day and year are missing but the date is valid.
|
||||
]
|
||||
list_as_string = '\n'.join(list_lot_and_qty)
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(list_as_string, move)
|
||||
self.assertEqual(len(move.move_line_ids), len(list_lot_and_qty))
|
||||
|
||||
self.assertEqual(move.move_line_ids[0].lot_name, "ln01")
|
||||
self.assertEqual(move.move_line_ids[0].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[0].expiration_date, datetime(day=31, month=12, year=2023))
|
||||
|
||||
self.assertEqual(move.move_line_ids[1].lot_name, "ln02")
|
||||
self.assertEqual(move.move_line_ids[1].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[1].expiration_date, datetime(day=17, month=4, year=1989))
|
||||
|
||||
self.assertEqual(move.move_line_ids[2].lot_name, "ln03")
|
||||
self.assertEqual(move.move_line_ids[2].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[2].expiration_date, today)
|
||||
|
||||
self.assertEqual(move.move_line_ids[3].lot_name, "ln04")
|
||||
self.assertEqual(move.move_line_ids[3].quantity, 1989)
|
||||
self.assertEqual(move.move_line_ids[3].expiration_date, today)
|
||||
|
||||
self.assertEqual(move.move_line_ids[4].lot_name, "ln05")
|
||||
self.assertEqual(move.move_line_ids[4].quantity, 1989.04)
|
||||
self.assertEqual(move.move_line_ids[4].expiration_date, today)
|
||||
|
||||
self.assertEqual(move.move_line_ids[5].lot_name, "ln06\t1989+04")
|
||||
self.assertEqual(move.move_line_ids[5].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[5].expiration_date, today)
|
||||
|
||||
self.assertEqual(move.move_line_ids[6].lot_name, "ln07\tdacember")
|
||||
self.assertEqual(move.move_line_ids[6].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[6].expiration_date, today)
|
||||
|
||||
self.assertEqual(move.move_line_ids[7].lot_name, "ln08")
|
||||
self.assertEqual(move.move_line_ids[7].quantity, 1)
|
||||
self.assertEqual(move.move_line_ids[7].expiration_date, datetime(day=17, month=12, year=2023))
|
||||
|
||||
def test_set_multiple_lot_name_with_expiration_date_06_one_line(self):
|
||||
""" Checks the pasted data are correctly parsed even if the user pastes only one line.
|
||||
"""
|
||||
user_lang = self.env['res.lang'].browse([get_lang(self.env).id])
|
||||
user_lang.date_format = "%d/%m/%y"
|
||||
for lot_name in ["lot-001;20;4 Aug 2048", "lot-001\t04/08/2048\t20"]:
|
||||
move = self.get_new_move(product=self.product_lot)
|
||||
self._import_lots(lot_name, move)
|
||||
self.assertEqual(move.move_line_ids.lot_name, "lot-001")
|
||||
self.assertEqual(move.move_line_ids.quantity, 20)
|
||||
self.assertEqual(move.move_line_ids.expiration_date, datetime(day=4, month=8, year=2048))
|
||||
|
||||
|
||||
class TestProductExpiryTour(TestStockPickingTour):
|
||||
|
||||
@freeze_time("2020-06-01")
|
||||
def test_generate_serial_with_expiration(self):
|
||||
"""
|
||||
Ensure that serial/lot numbers generated using the 'Generate Serials/Lots' button in Detailed
|
||||
Operations have expiration dates set.
|
||||
"""
|
||||
product_exp = self.env['product.product'].create({
|
||||
'name': 'Product Exp',
|
||||
'is_storable': True,
|
||||
'tracking': 'serial',
|
||||
'use_expiration_date': True,
|
||||
'expiration_time': 2,
|
||||
})
|
||||
|
||||
self.env['stock.move'].create({
|
||||
'product_id': product_exp.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': product_exp.uom_id.id,
|
||||
'picking_id': self.receipt.id,
|
||||
})
|
||||
|
||||
self.receipt.action_confirm()
|
||||
url = self._get_picking_url(self.receipt.id)
|
||||
|
||||
self.start_tour(url, 'test_generate_serial_with_expiration', login='admin')
|
||||
|
|
@ -4,10 +4,10 @@
|
|||
from datetime import datetime, timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import fields
|
||||
from odoo import fields, Command
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.addons.stock.tests.common import TestStockCommon
|
||||
from odoo.tests.common import Form
|
||||
from odoo.tests import Form
|
||||
|
||||
|
||||
class TestStockLot(TestStockCommon):
|
||||
|
|
@ -18,7 +18,7 @@ class TestStockLot(TestStockCommon):
|
|||
# Creates a tracked product with expiration dates.
|
||||
cls.apple_product = cls.ProductObj.create({
|
||||
'name': 'Apple',
|
||||
'type': 'product',
|
||||
'is_storable': True,
|
||||
'tracking': 'lot',
|
||||
'use_expiration_date': True,
|
||||
'expiration_time': 10,
|
||||
|
|
@ -33,7 +33,7 @@ class TestStockLot(TestStockCommon):
|
|||
# create product
|
||||
self.productAAA = self.ProductObj.create({
|
||||
'name': 'Product AAA',
|
||||
'type': 'product',
|
||||
'is_storable': True,
|
||||
'tracking':'lot',
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
|
@ -43,23 +43,22 @@ class TestStockLot(TestStockCommon):
|
|||
'name': 'Lot 1 ProductAAA',
|
||||
'product_id': self.productAAA.id,
|
||||
'alert_date': fields.Date.to_string(datetime.today() - relativedelta(days=15)),
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
picking_in = self.PickingObj.create({
|
||||
'picking_type_id': self.picking_type_in,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location
|
||||
'picking_type_id': self.picking_type_in.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'state': 'draft',
|
||||
})
|
||||
|
||||
move_a = self.MoveObj.create({
|
||||
'name': self.productAAA.name,
|
||||
'product_id': self.productAAA.id,
|
||||
'product_uom_qty': 33,
|
||||
'product_uom': self.productAAA.uom_id.id,
|
||||
'picking_id': picking_in.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
|
||||
self.assertEqual(picking_in.move_ids.state, 'draft', 'Wrong state of move line.')
|
||||
|
|
@ -68,17 +67,18 @@ class TestStockLot(TestStockCommon):
|
|||
|
||||
# Replace pack operation of incoming shipments.
|
||||
picking_in.action_assign()
|
||||
move_a.move_line_ids.qty_done = 33
|
||||
move_a.move_line_ids.quantity = 33
|
||||
move_a.move_line_ids.lot_id = self.lot1_productAAA.id
|
||||
|
||||
# Transfer Incoming Shipment.
|
||||
move_a.picked = True
|
||||
picking_in._action_done()
|
||||
|
||||
# run scheduled tasks
|
||||
self.env['stock.lot']._alert_date_exceeded()
|
||||
|
||||
# check a new activity has been created
|
||||
activity_id = self.env.ref('product_expiry.mail_activity_type_alert_date_reached').id
|
||||
activity_id = self.env.ref('mail.mail_activity_data_todo').id
|
||||
activity_count = self.env['mail.activity'].search_count([
|
||||
('activity_type_id', '=', activity_id),
|
||||
('res_model_id', '=', self.env.ref('stock.model_stock_lot').id),
|
||||
|
|
@ -130,7 +130,7 @@ class TestStockLot(TestStockCommon):
|
|||
# create product
|
||||
self.productBBB = self.ProductObj.create({
|
||||
'name': 'Product BBB',
|
||||
'type': 'product',
|
||||
'is_storable': True,
|
||||
'tracking':'lot'
|
||||
})
|
||||
|
||||
|
|
@ -139,22 +139,23 @@ class TestStockLot(TestStockCommon):
|
|||
'name': 'Lot 1 ProductBBB',
|
||||
'product_id': self.productBBB.id,
|
||||
'alert_date': fields.Date.to_string(datetime.today() + relativedelta(days=15)),
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
picking_in = self.PickingObj.create({
|
||||
'picking_type_id': self.picking_type_in,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
'picking_type_id': self.picking_type_in.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'state': 'draft',
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
|
||||
move_b = self.MoveObj.create({
|
||||
'name': self.productBBB.name,
|
||||
'product_id': self.productBBB.id,
|
||||
'product_uom_qty': 44,
|
||||
'product_uom': self.productBBB.uom_id.id,
|
||||
'picking_id': picking_in.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
|
||||
self.assertEqual(picking_in.move_ids.state, 'draft', 'Wrong state of move line.')
|
||||
picking_in.action_confirm()
|
||||
|
|
@ -162,7 +163,7 @@ class TestStockLot(TestStockCommon):
|
|||
|
||||
# Replace pack operation of incoming shipments.
|
||||
picking_in.action_assign()
|
||||
move_b.move_line_ids.qty_done = 44
|
||||
move_b.move_line_ids.quantity = 44
|
||||
move_b.move_line_ids.lot_id = self.lot1_productBBB.id
|
||||
|
||||
# Transfer Incoming Shipment.
|
||||
|
|
@ -172,7 +173,7 @@ class TestStockLot(TestStockCommon):
|
|||
self.env['stock.lot']._alert_date_exceeded()
|
||||
|
||||
# check a new activity has not been created
|
||||
activity_id = self.env.ref('product_expiry.mail_activity_type_alert_date_reached').id
|
||||
activity_id = self.env.ref('mail.mail_activity_data_todo').id
|
||||
activity_count = self.env['mail.activity'].search_count([
|
||||
('activity_type_id', '=', activity_id),
|
||||
('res_model_id', '=', self.env.ref('stock.model_stock_lot').id),
|
||||
|
|
@ -184,24 +185,26 @@ class TestStockLot(TestStockCommon):
|
|||
""" Test Scheduled Task on lot without an alert_date does not create an activity """
|
||||
|
||||
# create product
|
||||
self.productCCC = self.ProductObj.create({'name': 'Product CCC', 'type': 'product', 'tracking':'lot'})
|
||||
self.productCCC = self.ProductObj.create({'name': 'Product CCC', 'is_storable': True, 'tracking': 'lot'})
|
||||
|
||||
# create a new lot with with alert date in the past
|
||||
self.lot1_productCCC = self.LotObj.create({'name': 'Lot 1 ProductCCC', 'product_id': self.productCCC.id, 'company_id': self.env.company.id})
|
||||
self.lot1_productCCC = self.LotObj.create({'name': 'Lot 1 ProductCCC', 'product_id': self.productCCC.id})
|
||||
|
||||
picking_in = self.PickingObj.create({
|
||||
'picking_type_id': self.picking_type_in,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
'picking_type_id': self.picking_type_in.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'state': 'draft',
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
|
||||
move_c = self.MoveObj.create({
|
||||
'name': self.productCCC.name,
|
||||
'product_id': self.productCCC.id,
|
||||
'product_uom_qty': 44,
|
||||
'product_uom': self.productCCC.uom_id.id,
|
||||
'picking_id': picking_in.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
|
||||
self.assertEqual(picking_in.move_ids.state, 'draft', 'Wrong state of move line.')
|
||||
picking_in.action_confirm()
|
||||
|
|
@ -209,7 +212,7 @@ class TestStockLot(TestStockCommon):
|
|||
|
||||
# Replace pack operation of incoming shipments.
|
||||
picking_in.action_assign()
|
||||
move_c.move_line_ids.qty_done = 55
|
||||
move_c.move_line_ids.quantity = 55
|
||||
move_c.move_line_ids.lot_id = self.lot1_productCCC.id
|
||||
|
||||
# Transfer Incoming Shipment.
|
||||
|
|
@ -219,7 +222,7 @@ class TestStockLot(TestStockCommon):
|
|||
self.env['stock.lot']._alert_date_exceeded()
|
||||
|
||||
# check a new activity has not been created
|
||||
activity_id = self.env.ref('product_expiry.mail_activity_type_alert_date_reached').id
|
||||
activity_id = self.env.ref('mail.mail_activity_data_todo').id
|
||||
activity_count = self.env['mail.activity'].search_count([
|
||||
('activity_type_id', '=', activity_id),
|
||||
('res_model_id', '=', self.env.ref('stock.model_stock_lot').id),
|
||||
|
|
@ -251,7 +254,6 @@ class TestStockLot(TestStockCommon):
|
|||
lot_form = Form(self.LotObj)
|
||||
lot_form.name = 'Apple Box #1'
|
||||
lot_form.product_id = self.apple_product
|
||||
lot_form.company_id = self.env.company
|
||||
apple_lot = lot_form.save()
|
||||
# ...then checks date fields have the expected values.
|
||||
check_expiration_dates(self.apple_product, apple_lot, today_date, time_gap)
|
||||
|
|
@ -298,21 +300,21 @@ class TestStockLot(TestStockCommon):
|
|||
# Receives a tracked production using expiration date.
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
picking_form.picking_type_id = self.picking_type_in
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 4
|
||||
receipt = picking_form.save()
|
||||
receipt.action_confirm()
|
||||
|
||||
# Defines a date during the receipt.
|
||||
move_form = Form(receipt.move_ids_without_package, view="stock.view_stock_move_operations")
|
||||
with move_form.move_line_ids.new() as line:
|
||||
move_form = Form(receipt.move_ids, view="stock.view_stock_move_operations")
|
||||
with move_form.move_line_ids.edit(0) as line:
|
||||
line.lot_name = 'Apple Box #2'
|
||||
line.expiration_date = expiration_date
|
||||
line.qty_done = 4
|
||||
move = move_form.save()
|
||||
|
||||
move.picked = True
|
||||
receipt._action_done()
|
||||
# Get back the lot created when the picking was done...
|
||||
apple_lot = self.env['stock.lot'].search(
|
||||
|
|
@ -346,20 +348,19 @@ class TestStockLot(TestStockCommon):
|
|||
# Receives a tracked production using expiration date.
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
picking_form.picking_type_id = self.picking_type_in
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 4
|
||||
move.quantity = 4
|
||||
move.picked = True
|
||||
receipt = picking_form.save()
|
||||
receipt.action_confirm()
|
||||
|
||||
# Defines a date during the receipt.
|
||||
move = receipt.move_ids_without_package[0]
|
||||
move = receipt.move_ids[0]
|
||||
line = move.move_line_ids[0]
|
||||
self.assertEqual(move.use_expiration_date, True)
|
||||
line.lot_name = 'Apple Box #3'
|
||||
line.expiration_date = expiration_date
|
||||
line.qty_done = 4
|
||||
|
||||
receipt._action_done()
|
||||
# Get back the lot created when the picking was done...
|
||||
|
|
@ -390,13 +391,11 @@ class TestStockLot(TestStockCommon):
|
|||
lot_form = Form(self.LotObj) # Creates the lot.
|
||||
lot_form.name = 'good-apple-lot'
|
||||
lot_form.product_id = self.apple_product
|
||||
lot_form.company_id = self.env.company
|
||||
good_lot = lot_form.save()
|
||||
|
||||
lot_form = Form(self.LotObj) # Creates the lot.
|
||||
lot_form.name = 'expired-apple-lot-01'
|
||||
lot_form.product_id = self.apple_product
|
||||
lot_form.company_id = self.env.company
|
||||
expired_lot_1 = lot_form.save()
|
||||
lot_form = Form(expired_lot_1) # Edits the lot to make it expired.
|
||||
lot_form.expiration_date = datetime.today() - timedelta(days=10)
|
||||
|
|
@ -405,23 +404,24 @@ class TestStockLot(TestStockCommon):
|
|||
# Case #1: make a delivery with no expired lot.
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
picking_form.picking_type_id = self.picking_type_out
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 4
|
||||
# Saves and confirms it...
|
||||
delivery_1 = picking_form.save()
|
||||
delivery_1.action_confirm()
|
||||
# ... then create a move line with the non-expired lot and valids the picking.
|
||||
delivery_1.move_line_ids_without_package = [(5, 0), (0, 0, {
|
||||
delivery_1.move_line_ids = [(5, 0), (0, 0, {
|
||||
'company_id': self.env.company.id,
|
||||
'location_id': delivery_1.move_ids.location_id.id,
|
||||
'location_dest_id': delivery_1.move_ids.location_dest_id.id,
|
||||
'lot_id': good_lot.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'qty_done': 4,
|
||||
'quantity': 4,
|
||||
})]
|
||||
delivery_1.move_ids.picked = True
|
||||
res = delivery_1.button_validate()
|
||||
# Validate a delivery for good products must not raise anything.
|
||||
self.assertEqual(res, True)
|
||||
|
|
@ -429,8 +429,8 @@ class TestStockLot(TestStockCommon):
|
|||
# Case #2: make a delivery with one non-expired lot and one expired lot.
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
picking_form.picking_type_id = self.picking_type_out
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 8
|
||||
# Saves and confirms it...
|
||||
|
|
@ -438,14 +438,14 @@ class TestStockLot(TestStockCommon):
|
|||
delivery_2.action_confirm()
|
||||
# ... then create a move line for the non-expired lot and for an expired
|
||||
# lot and valids the picking.
|
||||
delivery_2.move_line_ids_without_package = [(5, 0), (0, 0, {
|
||||
delivery_2.move_line_ids = [(5, 0), (0, 0, {
|
||||
'company_id': self.env.company.id,
|
||||
'location_id': delivery_2.move_ids.location_id.id,
|
||||
'location_dest_id': delivery_2.move_ids.location_dest_id.id,
|
||||
'lot_id': good_lot.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'qty_done': 4,
|
||||
'quantity': 4,
|
||||
}), (0, 0, {
|
||||
'company_id': self.env.company.id,
|
||||
'location_id': delivery_2.move_ids.location_id.id,
|
||||
|
|
@ -453,8 +453,9 @@ class TestStockLot(TestStockCommon):
|
|||
'lot_id': expired_lot_1.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'qty_done': 4,
|
||||
'quantity': 4,
|
||||
})]
|
||||
delivery_2.move_ids.picked = True
|
||||
res = delivery_2.button_validate()
|
||||
# Validate a delivery containing expired products must raise a confirmation wizard.
|
||||
self.assertNotEqual(res, True)
|
||||
|
|
@ -463,23 +464,24 @@ class TestStockLot(TestStockCommon):
|
|||
# Case #3: make a delivery with only on expired lot.
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
picking_form.picking_type_id = self.picking_type_out
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 4
|
||||
# Saves and confirms it...
|
||||
delivery_3 = picking_form.save()
|
||||
delivery_3.action_confirm()
|
||||
# ... then create two move lines with expired lot and valids the picking.
|
||||
delivery_3.move_line_ids_without_package = [(5, 0), (0, 0, {
|
||||
delivery_3.move_line_ids = [(5, 0), (0, 0, {
|
||||
'company_id': self.env.company.id,
|
||||
'location_id': delivery_3.move_ids.location_id.id,
|
||||
'location_dest_id': delivery_3.move_ids.location_dest_id.id,
|
||||
'lot_id': expired_lot_1.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'qty_done': 4,
|
||||
'quantity': 4,
|
||||
})]
|
||||
delivery_3.move_ids.picked = True
|
||||
res = delivery_3.button_validate()
|
||||
# Validate a delivery containing expired products must raise a confirmation wizard.
|
||||
self.assertNotEqual(res, True)
|
||||
|
|
@ -499,12 +501,11 @@ class TestStockLot(TestStockCommon):
|
|||
lot_form = Form(self.LotObj)
|
||||
lot_form.name = 'LOT001'
|
||||
lot_form.product_id = self.apple_product
|
||||
lot_form.company_id = self.env.company
|
||||
apple_lot = lot_form.save()
|
||||
|
||||
quant = self.StockQuantObj.with_context(inventory_mode=True).create({
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 10,
|
||||
'lot_id': apple_lot.id,
|
||||
})
|
||||
|
|
@ -519,66 +520,35 @@ class TestStockLot(TestStockCommon):
|
|||
the latter should be applied on the SML
|
||||
"""
|
||||
exp_date = fields.Datetime.today() + relativedelta(days=15)
|
||||
sml_exp_date = fields.Datetime.today() + relativedelta(days=10)
|
||||
|
||||
lot = self.env['stock.lot'].create({
|
||||
'name': 'Lot 1',
|
||||
'product_id': self.apple_product.id,
|
||||
'expiration_date': fields.Datetime.to_string(exp_date),
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
move = self.env['stock.move'].create({
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom': self.apple_product.uom_id.id,
|
||||
})
|
||||
sml = self.env['stock.move.line'].create({
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.apple_product.id,
|
||||
'qty_done': 3,
|
||||
'quantity': 3,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'lot_id': lot.id,
|
||||
'expiration_date': fields.Datetime.to_string(sml_exp_date),
|
||||
'company_id': self.env.company.id,
|
||||
'move_id': move.id,
|
||||
})
|
||||
self.assertEqual(sml.expiration_date, sml_exp_date)
|
||||
|
||||
sml.lot_id = lot
|
||||
self.assertEqual(sml.expiration_date, exp_date)
|
||||
|
||||
exp_date = exp_date + relativedelta(days=10)
|
||||
lot.expiration_date = exp_date
|
||||
self.assertEqual(sml.expiration_date, exp_date)
|
||||
|
||||
def test_apply_lot_without_date_on_sml(self):
|
||||
"""
|
||||
When assigning a lot to a SML, if the lot has no expiration date,
|
||||
dates on lot and SML should be correctly set
|
||||
"""
|
||||
#create lot without expiration date
|
||||
lot = self.env['stock.lot'].create({
|
||||
'name': 'Lot 1',
|
||||
'product_id': self.apple_product.id,
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
sml = self.env['stock.move.line'].create({
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location,
|
||||
'product_id': self.apple_product.id,
|
||||
'qty_done': 3,
|
||||
'product_uom_id': self.apple_product.uom_id.id,
|
||||
'lot_id': lot.id,
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
today_date = datetime.today()
|
||||
time_gap = timedelta(seconds=10)
|
||||
exp_date = today_date + timedelta(days=self.apple_product.expiration_time)
|
||||
|
||||
self.assertAlmostEqual(sml.expiration_date, exp_date, delta=time_gap)
|
||||
|
||||
self.assertAlmostEqual(
|
||||
lot.expiration_date, exp_date, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
lot.use_date, exp_date - timedelta(days=self.apple_product.use_time), delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
lot.removal_date, exp_date - timedelta(days=self.apple_product.removal_time), delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
lot.alert_date, exp_date - timedelta(days=self.apple_product.alert_time), delta=time_gap)
|
||||
|
||||
def test_apply_same_date_on_expiry_fields(self):
|
||||
expiration_time = 10
|
||||
self.apple_product.write({
|
||||
|
|
@ -590,7 +560,6 @@ class TestStockLot(TestStockCommon):
|
|||
|
||||
lot = self.env['stock.lot'].create({
|
||||
'product_id': self.apple_product.id,
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
delta = timedelta(seconds=10)
|
||||
|
|
@ -601,6 +570,88 @@ class TestStockLot(TestStockCommon):
|
|||
self.assertAlmostEqual(lot.removal_date, expiration_date, delta=delta, msg=err_msg)
|
||||
self.assertAlmostEqual(lot.alert_date, expiration_date, delta=delta, msg=err_msg)
|
||||
|
||||
def test_no_expiration_date(self):
|
||||
"""
|
||||
When use_expiration_date is set to True on the Product, but the lot have an expiration_date set to False,
|
||||
the picking should be able to reserve on it because it is considered as 'non-perishable'
|
||||
"""
|
||||
lot_form = Form(self.LotObj)
|
||||
lot_form.name = 'LOT001'
|
||||
lot_form.product_id = self.apple_product
|
||||
apple_lot = lot_form.save()
|
||||
|
||||
lot_form = Form(apple_lot)
|
||||
lot_form.expiration_date = False
|
||||
lot_form.use_date = False
|
||||
lot_form.removal_date = False
|
||||
lot_form.alert_date = False
|
||||
apple_lot = lot_form.save()
|
||||
|
||||
self.StockQuantObj.with_context(inventory_mode=True).create({
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 100,
|
||||
'lot_id': apple_lot.id,
|
||||
})
|
||||
|
||||
self.assertEqual(self.apple_product.qty_available, 100, 'Wrong quantity.')
|
||||
|
||||
picking_out = self.PickingObj.create({
|
||||
'picking_type_id': self.picking_type_out.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'state': 'draft',
|
||||
})
|
||||
|
||||
self.MoveObj.create({
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': self.apple_product.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
})
|
||||
|
||||
self.assertEqual(picking_out.move_ids.state, 'draft', 'Wrong state of move line.')
|
||||
picking_out.action_confirm()
|
||||
picking_out.action_assign()
|
||||
self.assertEqual(picking_out.move_ids.state, 'assigned', 'Wrong state of move line.')
|
||||
|
||||
def test_no_lot(self):
|
||||
"""
|
||||
Try to reserve a move that for an expirable product that has both quants with and without lot attached.
|
||||
"""
|
||||
# Set the removal strategy to 'First Expiry First Out'
|
||||
fefo_strategy = self.env['product.removal'].search(
|
||||
[('method', '=', 'fefo')])
|
||||
self.apple_product.categ_id.removal_strategy_id = fefo_strategy.id
|
||||
|
||||
apple_lot = self.LotObj.create({
|
||||
'name': 'LOT001',
|
||||
'product_id': self.apple_product.id,
|
||||
})
|
||||
|
||||
self.StockQuantObj.with_context(inventory_mode=True).create([{
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 100,
|
||||
}, {
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 100,
|
||||
'lot_id': apple_lot.id,
|
||||
}])
|
||||
|
||||
with Form(self.PickingObj) as picking_form:
|
||||
picking_form.picking_type_id = self.picking_type_out
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 10
|
||||
picking_out = picking_form.save()
|
||||
|
||||
picking_out.action_assign()
|
||||
self.assertEqual(picking_out.move_line_ids.lot_id, apple_lot)
|
||||
|
||||
def test_compute_expiration_date_from_scheduled_date(self):
|
||||
partner = self.env['res.partner'].create({
|
||||
'name': 'Apple\'s Joe',
|
||||
|
|
@ -614,11 +665,98 @@ class TestStockLot(TestStockCommon):
|
|||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.partner_id = partner
|
||||
picking_form.scheduled_date = new_date
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
|
||||
picking_form.picking_type_id = self.picking_type_in
|
||||
|
||||
with picking_form.move_ids_without_package.new() as move:
|
||||
with picking_form.move_ids.new() as move:
|
||||
move.product_id = self.apple_product
|
||||
move.product_uom_qty = 4
|
||||
delivery = picking_form.save()
|
||||
delivery.action_confirm()
|
||||
|
||||
self.assertAlmostEqual(delivery.move_line_ids[0].expiration_date, expiration_date, delta=delta)
|
||||
|
||||
def test_compute_display_name(self):
|
||||
apple_lot1 = self.LotObj.create({
|
||||
'name': 'LOT-00001',
|
||||
'product_id': self.apple_product.id,
|
||||
'expiration_date': False,
|
||||
'alert_date': False,
|
||||
})
|
||||
apple_lot2 = self.LotObj.create({
|
||||
'name': 'LOT-00002',
|
||||
'product_id': self.apple_product.id,
|
||||
'expiration_date': datetime.today() - timedelta(days=10),
|
||||
})
|
||||
apple_lot3 = self.LotObj.create({
|
||||
'name': 'LOT-00003',
|
||||
'product_id': self.apple_product.id,
|
||||
'alert_date': datetime.today() - timedelta(days=10),
|
||||
})
|
||||
self.assertEqual(apple_lot1.with_context(formatted_display_name=True).display_name, "LOT-00001")
|
||||
self.assertEqual(apple_lot2.with_context(formatted_display_name=True).display_name, "LOT-00002\t--Expired--")
|
||||
self.assertEqual(apple_lot3.with_context(formatted_display_name=True).display_name, "LOT-00003\t--Expire on " + fields.Datetime.to_string(apple_lot3.expiration_date) + "--")
|
||||
|
||||
def test_proceed_except_expired_delivery_without_move_removal_date(self):
|
||||
lot = self.LotObj.create({
|
||||
'name': 'LOT-001',
|
||||
'product_id': self.apple_product.id,
|
||||
})
|
||||
lot.removal_date = False
|
||||
|
||||
self.StockQuantObj.with_context(inventory_mode=True).create({
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 100,
|
||||
'lot_id': lot.id,
|
||||
})
|
||||
picking = self.PickingObj.create({
|
||||
'partner_id': self.partner_1.id,
|
||||
'picking_type_id': self.picking_type_out.id,
|
||||
'move_ids': [Command.create({
|
||||
'product_id': self.apple_product.id,
|
||||
'product_uom_qty': 2,
|
||||
})],
|
||||
})
|
||||
picking.button_validate()
|
||||
context = {
|
||||
'button_validate_picking_ids': [picking.id],
|
||||
'default_picking_ids': [picking.id],
|
||||
'default_lot_ids': [lot.id],
|
||||
}
|
||||
wizard = self.env['expiry.picking.confirmation'].with_context(context).create({})
|
||||
self.assertFalse(wizard.picking_ids.move_line_ids.removal_date)
|
||||
wizard.process_no_expired()
|
||||
|
||||
def test_lot_dates_form_update(self):
|
||||
"""
|
||||
Ensure that we can edit the removal_date and expiration_date fields at the same time
|
||||
Without triggering the compute method for the expiration when saving modifications.
|
||||
"""
|
||||
delta = timedelta(seconds=10)
|
||||
today = datetime.today()
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'picking_type_id': self.picking_type_in.id,
|
||||
'scheduled_date': today,
|
||||
'move_ids': [
|
||||
Command.create({
|
||||
'product_id': self.apple_product.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_qty': 1,
|
||||
}),
|
||||
],
|
||||
})
|
||||
receipt.action_confirm()
|
||||
self.assertAlmostEqual(receipt.move_line_ids.expiration_date, today + timedelta(days=10), delta=delta)
|
||||
self.assertAlmostEqual(receipt.move_line_ids.removal_date, today + timedelta(days=8), delta=delta)
|
||||
|
||||
with Form(receipt.move_ids, view="stock.view_stock_move_operations") as move_form:
|
||||
with move_form.move_line_ids.edit(0) as line_form:
|
||||
line_form.lot_name = 'lot 1'
|
||||
line_form.expiration_date = today + timedelta(days=15)
|
||||
line_form.removal_date = today + timedelta(days=10)
|
||||
|
||||
self.assertAlmostEqual(receipt.move_line_ids.expiration_date, today + timedelta(days=15), delta=delta)
|
||||
self.assertAlmostEqual(receipt.move_line_ids.removal_date, today + timedelta(days=10), delta=delta)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue