summaryrefslogtreecommitdiff
path: root/addons/sale_stock/tests/test_sale_stock_lead_time.py
blob: 00339f1c5421d0027e1f2df375b114821aac1693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
from odoo.addons.sale.tests.common import TestSaleCommon
from odoo import fields
from odoo.tests import tagged

from datetime import timedelta


@tagged('post_install', '-at_install')
class TestSaleStockLeadTime(TestSaleCommon, ValuationReconciliationTestCommon):

    @classmethod
    def setUpClass(cls, chart_template_ref=None):
        super().setUpClass(chart_template_ref=chart_template_ref)

        # Update the product_1 with type and Customer Lead Time
        cls.test_product_order.sale_delay = 5.0

    def test_00_product_company_level_delays(self):
        """ In order to check schedule date, set product's Customer Lead Time
            and company's Sales Safety Days."""

        # Update company with Sales Safety Days
        self.env.company.security_lead = 3.00

        # Create sale order of product_1
        order = self.env['sale.order'].create({
            'partner_id': self.partner_a.id,
            'partner_invoice_id': self.partner_a.id,
            'partner_shipping_id': self.partner_a.id,
            'pricelist_id': self.company_data['default_pricelist'].id,
            'picking_policy': 'direct',
            'warehouse_id': self.company_data['default_warehouse'].id,
            'order_line': [(0, 0, {'name': self.test_product_order.name,
                                   'product_id': self.test_product_order.id,
                                   'product_uom_qty': 10,
                                   'product_uom': self.env.ref('uom.product_uom_unit').id,
                                   'customer_lead': self.test_product_order.sale_delay})]})

        # Confirm our standard sale order
        order.action_confirm()

        # Check the picking crated or not
        self.assertTrue(order.picking_ids, "Picking should be created.")

        # Check schedule date of picking
        out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=self.env.company.security_lead)
        min_date = fields.Datetime.from_string(order.picking_ids[0].scheduled_date)
        self.assertTrue(abs(min_date - out_date) <= timedelta(seconds=1), 'Schedule date of picking should be equal to: order date + Customer Lead Time - Sales Safety Days.')

    def test_01_product_route_level_delays(self):
        """ In order to check schedule dates, set product's Customer Lead Time
            and warehouse route's delay."""

        # Update warehouse_1 with Outgoing Shippings pick + pack + ship
        self.company_data['default_warehouse'].write({'delivery_steps': 'pick_pack_ship'})

        # Set delay on pull rule
        for pull_rule in self.company_data['default_warehouse'].delivery_route_id.rule_ids:
            pull_rule.write({'delay': 2})

        # Create sale order of product_1
        order = self.env['sale.order'].create({
            'partner_id': self.partner_a.id,
            'partner_invoice_id': self.partner_a.id,
            'partner_shipping_id': self.partner_a.id,
            'pricelist_id': self.company_data['default_pricelist'].id,
            'picking_policy': 'direct',
            'warehouse_id': self.company_data['default_warehouse'].id,
            'order_line': [(0, 0, {'name': self.test_product_order.name,
                                   'product_id': self.test_product_order.id,
                                   'product_uom_qty': 5,
                                   'product_uom': self.env.ref('uom.product_uom_unit').id,
                                   'customer_lead': self.test_product_order.sale_delay})]})

        # Confirm our standard sale order
        order.action_confirm()

        # Check the picking crated or not
        self.assertTrue(order.picking_ids, "Pickings should be created.")

        # Check schedule date of ship type picking
        out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].out_type_id)
        out_min_date = fields.Datetime.from_string(out.scheduled_date)
        out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
        self.assertTrue(abs(out_min_date - out_date) <= timedelta(seconds=1), 'Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.')

        # Check schedule date of pack type picking
        pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pack_type_id)
        pack_min_date = fields.Datetime.from_string(pack.scheduled_date)
        pack_date = out_date - timedelta(days=pack.move_lines[0].rule_id.delay)
        self.assertTrue(abs(pack_min_date - pack_date) <= timedelta(seconds=1), 'Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')

        # Check schedule date of pick type picking
        pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pick_type_id)
        pick_min_date = fields.Datetime.from_string(pick.scheduled_date)
        pick_date = pack_date - timedelta(days=pick.move_lines[0].rule_id.delay)
        self.assertTrue(abs(pick_min_date - pick_date) <= timedelta(seconds=1), 'Schedule date of pick type picking should be equal to: Schedule date of pack type picking - pull rule delay.')

    def test_02_delivery_date_propagation(self):
        """ In order to check deadline date propagation, set product's Customer Lead Time
            and warehouse route's delay in stock rules"""

        # Example :
        # -> Set Warehouse with Outgoing Shipments : pick + pack + ship
        # -> Set Delay : 5 days on stock rules
        # -> Set Customer Lead Time on product : 30 days
        # -> Set Sales Safety Days : 2 days
        # -> Create an SO and confirm it with confirmation Date : 12/18/2018

        # -> Pickings : OUT -> Scheduled Date : 01/12/2019, Deadline Date: 01/14/2019
        #              PACK -> Scheduled Date : 01/07/2019, Deadline Date: 01/09/2019
        #              PICK -> Scheduled Date : 01/02/2019, Deadline Date: 01/04/2019

        # -> Now, change commitment_date in the sale order = out_deadline_date + 5 days

        # -> Deadline Date should be changed and Scheduled date should be unchanged:
        #              OUT  -> Deadline Date : 01/19/2019
        #              PACK -> Deadline Date : 01/14/2019
        #              PICK -> Deadline Date : 01/09/2019

        # Update company with Sales Safety Days
        self.env.company.security_lead = 2.00

        # Update warehouse_1 with Outgoing Shippings pick + pack + ship
        self.company_data['default_warehouse'].write({'delivery_steps': 'pick_pack_ship'})

        # Set delay on pull rule
        self.company_data['default_warehouse'].delivery_route_id.rule_ids.write({'delay': 5})

        # Update the product_1 with type and Customer Lead Time
        self.test_product_order.write({'type': 'product', 'sale_delay': 30.0})

        # Now, create sale order of product_1 with customer_lead set on product
        order = self.env['sale.order'].create({
            'partner_id': self.partner_a.id,
            'partner_invoice_id': self.partner_a.id,
            'partner_shipping_id': self.partner_a.id,
            'pricelist_id': self.company_data['default_pricelist'].id,
            'picking_policy': 'direct',
            'warehouse_id': self.company_data['default_warehouse'].id,
            'order_line': [(0, 0, {'name': self.test_product_order.name,
                                   'product_id': self.test_product_order.id,
                                   'product_uom_qty': 5,
                                   'product_uom': self.env.ref('uom.product_uom_unit').id,
                                   'customer_lead': self.test_product_order.sale_delay})]})

        # Confirm our standard sale order
        order.action_confirm()

        # Check the picking crated or not
        self.assertTrue(order.picking_ids, "Pickings should be created.")

        # Check schedule/deadline date of ship type picking
        out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].out_type_id)
        deadline_date = order.date_order + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            out.date_deadline, deadline_date, delta=timedelta(seconds=1),
            msg='Deadline date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.')
        out_scheduled_date = deadline_date - timedelta(days=self.env.company.security_lead)
        self.assertAlmostEqual(
            out.scheduled_date, out_scheduled_date, delta=timedelta(seconds=1),
            msg='Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay - security_lead')

        # Check schedule/deadline date of pack type picking
        pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pack_type_id)
        pack_scheduled_date = out_scheduled_date - timedelta(days=pack.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            pack.scheduled_date, pack_scheduled_date, delta=timedelta(seconds=1),
            msg='Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')
        deadline_date -= timedelta(days=pack.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            pack.date_deadline, deadline_date, delta=timedelta(seconds=1),
            msg='Deadline date of pack type picking should be equal to: Deadline date of ship type picking - pull rule delay.')

        # Check schedule/deadline date of pick type picking
        pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pick_type_id)
        pick_scheduled_date = pack_scheduled_date - timedelta(days=pick.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            pick.scheduled_date, pick_scheduled_date, delta=timedelta(seconds=1),
            msg='Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')
        deadline_date -= timedelta(days=pick.move_lines[0].rule_id.delay)
        self.assertAlmostEqual(
            pick.date_deadline, deadline_date, delta=timedelta(seconds=1),
            msg='Deadline date of pack type picking should be equal to: Deadline date of ship type picking - pull rule delay.')

        # Now change the commitment date (Delivery Date) of the sale order
        new_deadline = deadline_date + timedelta(days=5)
        order.write({'commitment_date': new_deadline})

        # Now check date_deadline of pick, pack and out are forced
        # TODO : add note in case of change of deadline and check
        self.assertEqual(out.date_deadline, new_deadline)
        new_deadline -= timedelta(days=pack.move_lines[0].rule_id.delay)
        self.assertEqual(pack.date_deadline, new_deadline)
        new_deadline -= timedelta(days=pick.move_lines[0].rule_id.delay)
        self.assertEqual(pick.date_deadline, new_deadline)