summaryrefslogtreecommitdiff
path: root/addons/purchase_stock/tests/test_purchase_lead_time.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/purchase_stock/tests/test_purchase_lead_time.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/purchase_stock/tests/test_purchase_lead_time.py')
-rw-r--r--addons/purchase_stock/tests/test_purchase_lead_time.py341
1 files changed, 341 insertions, 0 deletions
diff --git a/addons/purchase_stock/tests/test_purchase_lead_time.py b/addons/purchase_stock/tests/test_purchase_lead_time.py
new file mode 100644
index 00000000..6fbae5c5
--- /dev/null
+++ b/addons/purchase_stock/tests/test_purchase_lead_time.py
@@ -0,0 +1,341 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from datetime import datetime, timedelta, time
+from unittest.mock import patch
+
+from odoo import fields
+from .common import PurchaseTestCommon
+from odoo.tests.common import Form
+
+
+class TestPurchaseLeadTime(PurchaseTestCommon):
+
+ def test_00_product_company_level_delays(self):
+ """ To check dates, set product's Delivery Lead Time
+ and company's Purchase Lead Time."""
+
+ company = self.env.ref('base.main_company')
+
+ # Update company with Purchase Lead Time
+ company.write({'po_lead': 3.00})
+
+ # Make procurement request from product_1's form view, create procurement and check it's state
+ date_planned = fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10))
+ self._create_make_procurement(self.product_1, 15.00, date_planned=date_planned)
+ purchase = self.env['purchase.order.line'].search([('product_id', '=', self.product_1.id)], limit=1).order_id
+
+ # Confirm purchase order
+ purchase.button_confirm()
+
+ # Check order date of purchase order
+ order_date = fields.Datetime.from_string(date_planned) - timedelta(days=company.po_lead) - timedelta(days=self.product_1.seller_ids.delay)
+ self.assertEqual(purchase.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Purchase Lead Time - Delivery Lead Time.')
+
+ # Check scheduled date of purchase order
+ schedule_date = datetime.combine(order_date + timedelta(days=self.product_1.seller_ids.delay), time.min).replace(tzinfo=None, hour=12)
+ self.assertEqual(purchase.order_line.date_planned, schedule_date, 'Schedule date should be equal to: Order date of Purchase order + Delivery Lead Time.')
+
+ # check the picking created or not
+ self.assertTrue(purchase.picking_ids, "Picking should be created.")
+
+ # Check scheduled and deadline date of In Type shipment
+ self.assertEqual(purchase.picking_ids.scheduled_date, schedule_date, 'Schedule date of In type shipment should be equal to: schedule date of purchase order.')
+ self.assertEqual(purchase.picking_ids.date_deadline, schedule_date + timedelta(days=company.po_lead), 'Deadline date of should be equal to: schedule date of purchase order + lead_po.')
+
+ def test_01_product_level_delay(self):
+ """ To check schedule dates of multiple purchase order line of the same purchase order,
+ we create two procurements for the two different product with same vendor
+ and different Delivery Lead Time."""
+
+ company = self.env.ref('base.main_company')
+ company.write({'po_lead': 0.00})
+
+ # Make procurement request from product_1's form view, create procurement and check it's state
+ date_planned1 = fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10))
+ self._create_make_procurement(self.product_1, 10.00, date_planned=date_planned1)
+ purchase1 = self.env['purchase.order.line'].search([('product_id', '=', self.product_1.id)], limit=1).order_id
+
+ # Make procurement request from product_2's form view, create procurement and check it's state
+ date_planned2 = fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10))
+ self._create_make_procurement(self.product_2, 5.00, date_planned=date_planned2)
+ purchase2 = self.env['purchase.order.line'].search([('product_id', '=', self.product_2.id)], limit=1).order_id
+
+ # Check purchase order is same or not
+ self.assertEqual(purchase1, purchase2, 'Purchase orders should be same for the two different product with same vendor.')
+
+ # Confirm purchase order
+ purchase1.button_confirm()
+
+ # Check order date of purchase order
+ order_line_pro_1 = purchase2.order_line.filtered(lambda r: r.product_id == self.product_1)
+ order_line_pro_2 = purchase2.order_line.filtered(lambda r: r.product_id == self.product_2)
+ order_date = fields.Datetime.from_string(date_planned1) - timedelta(days=self.product_1.seller_ids.delay)
+ self.assertEqual(purchase2.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Delivery Lead Time.')
+
+ # Check scheduled date of purchase order line for product_1
+ schedule_date_1 = datetime.combine(order_date + timedelta(days=self.product_1.seller_ids.delay), time.min).replace(tzinfo=None, hour=12)
+ self.assertEqual(order_line_pro_1.date_planned, schedule_date_1, 'Schedule date of purchase order line for product_1 should be equal to: Order date of purchase order + Delivery Lead Time of product_1.')
+
+ # Check scheduled date of purchase order line for product_2
+ schedule_date_2 = datetime.combine(order_date + timedelta(days=self.product_2.seller_ids.delay), time.min).replace(tzinfo=None, hour=12)
+ self.assertEqual(order_line_pro_2.date_planned, schedule_date_2, 'Schedule date of purchase order line for product_2 should be equal to: Order date of purchase order + Delivery Lead Time of product_2.')
+
+ # Check scheduled date of purchase order
+ po_schedule_date = min(schedule_date_1, schedule_date_2)
+ self.assertEqual(purchase2.order_line[1].date_planned, po_schedule_date, 'Schedule date of purchase order should be minimum of schedule dates of purchase order lines.')
+
+ # Check the picking created or not
+ self.assertTrue(purchase2.picking_ids, "Picking should be created.")
+
+ # Check scheduled date of In Type shipment
+ self.assertEqual(purchase2.picking_ids.scheduled_date, po_schedule_date, 'Schedule date of In type shipment should be same as schedule date of purchase order.')
+
+ # Check deadline of pickings
+ self.assertEqual(purchase2.picking_ids.date_deadline, purchase2.date_planned, "Deadline of pickings should be equals to the receipt date of purchase")
+ purchase_form = Form(purchase2)
+ purchase_form.date_planned = purchase2.date_planned + timedelta(days=2)
+ purchase_form.save()
+ self.assertEqual(purchase2.picking_ids.date_deadline, purchase2.date_planned, "Deadline of pickings should be propagate")
+
+ def test_02_product_route_level_delays(self):
+ """ In order to check dates, set product's Delivery Lead Time
+ and warehouse route's delay."""
+
+ company = self.env.ref('base.main_company')
+ company.write({'po_lead': 1.00})
+
+ # Update warehouse_1 with Incoming Shipments 3 steps
+ self.warehouse_1.write({'reception_steps': 'three_steps'})
+
+ # Set delay on push rule
+ for push_rule in self.warehouse_1.reception_route_id.rule_ids:
+ push_rule.write({'delay': 2})
+
+ rule_delay = sum(self.warehouse_1.reception_route_id.rule_ids.mapped('delay'))
+
+ date_planned = fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10))
+ # Create procurement order of product_1
+ self.env['procurement.group'].run([self.env['procurement.group'].Procurement(
+ self.product_1, 5.000, self.uom_unit, self.warehouse_1.lot_stock_id, 'Test scheduler for RFQ', '/', self.env.company,
+ {
+ 'warehouse_id': self.warehouse_1,
+ 'date_planned': date_planned, # 10 days added to current date of procurement to get future schedule date and order date of purchase order.
+ 'date_deadline': date_planned, # 10 days added to current date of procurement to get future schedule date and order date of purchase order.
+ 'rule_id': self.warehouse_1.buy_pull_id,
+ 'group_id': False,
+ 'route_ids': [],
+ }
+ )])
+
+ # Confirm purchase order
+ purchase = self.env['purchase.order.line'].search([('product_id', '=', self.product_1.id)], limit=1).order_id
+ purchase.button_confirm()
+
+ # Check order date of purchase order
+ order_date = fields.Datetime.from_string(date_planned) - timedelta(days=self.product_1.seller_ids.delay + rule_delay + company.po_lead)
+ self.assertEqual(purchase.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Delivery Lead Time(supplier and pull rules).')
+
+ # Check scheduled date of purchase order
+ schedule_date = order_date + timedelta(days=self.product_1.seller_ids.delay + rule_delay + company.po_lead)
+ self.assertEqual(date_planned, str(schedule_date), 'Schedule date should be equal to: Order date of Purchase order + Delivery Lead Time(supplier and pull rules).')
+
+ # Check the picking crated or not
+ self.assertTrue(purchase.picking_ids, "Picking should be created.")
+
+ # Check scheduled date of Internal Type shipment
+ incoming_shipment1 = self.env['stock.picking'].search([('move_lines.product_id', 'in', (self.product_1.id, self.product_2.id)), ('picking_type_id', '=', self.warehouse_1.int_type_id.id), ('location_id', '=', self.warehouse_1.wh_input_stock_loc_id.id), ('location_dest_id', '=', self.warehouse_1.wh_qc_stock_loc_id.id)])
+ incoming_shipment1_date = order_date + timedelta(days=self.product_1.seller_ids.delay + company.po_lead)
+ self.assertEqual(incoming_shipment1.scheduled_date, incoming_shipment1_date, 'Schedule date of Internal Type shipment for input stock location should be equal to: schedule date of purchase order + push rule delay.')
+ self.assertEqual(incoming_shipment1.date_deadline, incoming_shipment1_date)
+ old_deadline1 = incoming_shipment1.date_deadline
+
+ incoming_shipment2 = self.env['stock.picking'].search([('picking_type_id', '=', self.warehouse_1.int_type_id.id), ('location_id', '=', self.warehouse_1.wh_qc_stock_loc_id.id), ('location_dest_id', '=', self.warehouse_1.lot_stock_id.id)])
+ incoming_shipment2_date = schedule_date - timedelta(days=incoming_shipment2.move_lines[0].rule_id.delay)
+ self.assertEqual(incoming_shipment2.scheduled_date, incoming_shipment2_date, 'Schedule date of Internal Type shipment for quality control stock location should be equal to: schedule date of Internal type shipment for input stock location + push rule delay..')
+ self.assertEqual(incoming_shipment2.date_deadline, incoming_shipment2_date)
+ old_deadline2 = incoming_shipment2.date_deadline
+
+ # Modify the date_planned of the purchase -> propagate the deadline
+ purchase_form = Form(purchase)
+ purchase_form.date_planned = purchase.date_planned + timedelta(days=1)
+ purchase_form.save()
+ self.assertEqual(incoming_shipment2.date_deadline, old_deadline2 + timedelta(days=1), 'Deadline should be propagate')
+ self.assertEqual(incoming_shipment1.date_deadline, old_deadline1 + timedelta(days=1), 'Deadline should be propagate')
+
+ def test_merge_po_line(self):
+ """Change that merging po line for same procurement is done."""
+
+ # create a product with manufacture route
+ product_1 = self.env['product.product'].create({
+ 'name': 'AAA',
+ 'route_ids': [(4, self.route_buy)],
+ 'seller_ids': [(0, 0, {'name': self.partner_1.id, 'delay': 5})]
+ })
+
+ # create a move for product_1 from stock to output and reserve to trigger the
+ # rule
+ move_1 = self.env['stock.move'].create({
+ 'name': 'move_1',
+ 'product_id': product_1.id,
+ 'product_uom': self.ref('uom.product_uom_unit'),
+ 'location_id': self.ref('stock.stock_location_stock'),
+ 'location_dest_id': self.ref('stock.stock_location_output'),
+ 'product_uom_qty': 10,
+ 'procure_method': 'make_to_order'
+ })
+
+ move_1._action_confirm()
+ po_line = self.env['purchase.order.line'].search([
+ ('product_id', '=', product_1.id),
+ ])
+ self.assertEqual(len(po_line), 1, 'the purchase order line is not created')
+ self.assertEqual(po_line.product_qty, 10, 'the purchase order line has a wrong quantity')
+
+ move_2 = self.env['stock.move'].create({
+ 'name': 'move_2',
+ 'product_id': product_1.id,
+ 'product_uom': self.ref('uom.product_uom_unit'),
+ 'location_id': self.ref('stock.stock_location_stock'),
+ 'location_dest_id': self.ref('stock.stock_location_output'),
+ 'product_uom_qty': 5,
+ 'procure_method': 'make_to_order'
+ })
+
+ move_2._action_confirm()
+ po_line = self.env['purchase.order.line'].search([
+ ('product_id', '=', product_1.id),
+ ])
+ self.assertEqual(len(po_line), 1, 'the purchase order lines should be merged')
+ self.assertEqual(po_line.product_qty, 15, 'the purchase order line has a wrong quantity')
+
+ def test_merge_po_line_3(self):
+ """Change merging po line if same procurement is done depending on custom values."""
+ company = self.env.ref('base.main_company')
+ company.write({'po_lead': 0.00})
+
+ # The seller has a specific product name and code which must be kept in the PO line
+ self.t_shirt.seller_ids.write({
+ 'product_name': 'Vendor Name',
+ 'product_code': 'Vendor Code',
+ })
+ partner = self.t_shirt.seller_ids[:1].name
+ t_shirt = self.t_shirt.with_context(
+ lang=partner.lang,
+ partner_id=partner.id,
+ )
+
+ # Create procurement order of product_1
+ ProcurementGroup = self.env['procurement.group']
+ procurement_values = {
+ 'warehouse_id': self.warehouse_1,
+ 'rule_id': self.warehouse_1.buy_pull_id,
+ 'date_planned': fields.Datetime.to_string(fields.datetime.now() + timedelta(days=10)),
+ 'group_id': False,
+ 'route_ids': [],
+ }
+
+ procurement_values['product_description_variants'] = 'Color (Red)'
+ order_1_values = procurement_values
+ ProcurementGroup.run([self.env['procurement.group'].Procurement(
+ self.t_shirt, 5, self.uom_unit, self.warehouse_1.lot_stock_id,
+ self.t_shirt.name, '/', self.env.company, order_1_values)
+ ])
+ purchase_order = self.env['purchase.order.line'].search([('product_id', '=', self.t_shirt.id)], limit=1).order_id
+ order_line_description = purchase_order.order_line.product_id._get_description(purchase_order.picking_type_id)
+ self.assertEqual(len(purchase_order.order_line), 1, 'wrong number of order line is created')
+ self.assertEqual(purchase_order.order_line.name, t_shirt.display_name + "\n" + "Color (Red)", 'wrong description in po lines')
+
+ procurement_values['product_description_variants'] = 'Color (Red)'
+ order_2_values = procurement_values
+ ProcurementGroup.run([self.env['procurement.group'].Procurement(
+ self.t_shirt, 10, self.uom_unit, self.warehouse_1.lot_stock_id,
+ self.t_shirt.name, '/', self.env.company, order_2_values)
+ ])
+ self.env['procurement.group'].run_scheduler()
+ self.assertEqual(len(purchase_order.order_line), 1, 'line with same custom value should be merged')
+ self.assertEqual(purchase_order.order_line[0].product_qty, 15, 'line with same custom value should be merged and qty should be update')
+
+ procurement_values['product_description_variants'] = 'Color (Green)'
+
+ order_3_values = procurement_values
+ ProcurementGroup.run([self.env['procurement.group'].Procurement(
+ self.t_shirt, 10, self.uom_unit, self.warehouse_1.lot_stock_id,
+ self.t_shirt.name, '/', self.env.company, order_3_values)
+ ])
+ self.assertEqual(len(purchase_order.order_line), 2, 'line with different custom value should not be merged')
+ self.assertEqual(purchase_order.order_line.filtered(lambda x: x.product_qty == 15).name, t_shirt.display_name + "\n" + "Color (Red)", 'wrong description in po lines')
+ self.assertEqual(purchase_order.order_line.filtered(lambda x: x.product_qty == 10).name, t_shirt.display_name + "\n" + "Color (Green)", 'wrong description in po lines')
+
+ purchase_order.button_confirm()
+ self.assertEqual(purchase_order.picking_ids[0].move_ids_without_package.filtered(lambda x: x.product_uom_qty == 15).description_picking, order_line_description + "\nColor (Red)", 'wrong description in picking')
+ self.assertEqual(purchase_order.picking_ids[0].move_ids_without_package.filtered(lambda x: x.product_uom_qty == 10).description_picking, order_line_description + "\nColor (Green)", 'wrong description in picking')
+
+ def test_reordering_days_to_purchase(self):
+ company = self.env.ref('base.main_company')
+ company2 = self.env['res.company'].create({
+ 'name': 'Second Company',
+ })
+ company.write({'po_lead': 0.00})
+ self.patcher = patch('odoo.addons.stock.models.stock_orderpoint.fields.Date', wraps=fields.Date)
+ self.mock_date = self.patcher.start()
+
+ vendor = self.env['res.partner'].create({
+ 'name': 'Colruyt'
+ })
+ vendor2 = self.env['res.partner'].create({
+ 'name': 'Delhaize'
+ })
+
+ self.env.company.days_to_purchase = 2.0
+
+ product = self.env['product.product'].create({
+ 'name': 'Chicory',
+ 'type': 'product',
+ 'seller_ids': [
+ (0, 0, {'name': vendor2.id, 'delay': 15.0, 'company_id': company2.id}),
+ (0, 0, {'name': vendor.id, 'delay': 1.0, 'company_id': company.id})
+ ]
+ })
+ orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
+ orderpoint_form.product_id = product
+ orderpoint_form.product_min_qty = 0.0
+ orderpoint = orderpoint_form.save()
+
+ orderpoint_form = Form(self.env['stock.warehouse.orderpoint'].with_company(company2))
+ orderpoint_form.product_id = product
+ orderpoint_form.product_min_qty = 0.0
+ orderpoint = orderpoint_form.save()
+
+ warehouse = self.env['stock.warehouse'].search([], limit=1)
+ delivery_moves = self.env['stock.move']
+ for i in range(0, 6):
+ delivery_moves |= self.env['stock.move'].create({
+ 'name': 'Delivery',
+ 'date': datetime.today() + timedelta(days=i),
+ 'product_id': product.id,
+ 'product_uom': product.uom_id.id,
+ 'product_uom_qty': 5.0,
+ 'location_id': warehouse.lot_stock_id.id,
+ 'location_dest_id': self.ref('stock.stock_location_customers'),
+ })
+ delivery_moves._action_confirm()
+ self.env['procurement.group'].run_scheduler()
+ po_line = self.env['purchase.order.line'].search([('product_id', '=', product.id)])
+ self.assertEqual(fields.Date.to_date(po_line.order_id.date_order), fields.Date.today() + timedelta(days=2))
+ self.assertEqual(len(po_line), 1)
+ self.assertEqual(po_line.product_uom_qty, 20.0)
+ self.assertEqual(len(po_line.order_id), 1)
+ orderpoint_form = Form(orderpoint)
+ orderpoint_form.save()
+
+ self.mock_date.today.return_value = fields.Date.today() + timedelta(days=1)
+ orderpoint._compute_qty()
+ self.env['procurement.group'].run_scheduler()
+ po_line = self.env['purchase.order.line'].search([('product_id', '=', product.id)])
+ self.assertEqual(len(po_line), 2)
+ self.assertEqual(len(po_line.order_id), 2)
+ new_order = po_line.order_id.sorted('date_order')[-1]
+ self.assertEqual(fields.Date.to_date(new_order.date_order), fields.Date.today() + timedelta(days=2))
+ self.assertEqual(new_order.order_line.product_uom_qty, 5.0)
+ self.patcher.stop()