Skip to content

Commit

Permalink
fixup! fixup! sale_delivery_date: Fix late expeditions detection
Browse files Browse the repository at this point in the history
  • Loading branch information
mmequignon committed Dec 1, 2023
1 parent 495acda commit 11783a5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 41 deletions.
80 changes: 47 additions & 33 deletions sale_delivery_date/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,42 @@ def _get_delays(self):
workload = max(customer_lead - security_lead, 0.0)
return customer_lead, security_lead, workload

def _get_expected_expedition_date(self):
"""Retrieves the latest expedition date from date_deadline"""
self.ensure_one()
sale_line_model = self.env["sale.order.line"]
delays = self._get_delays()
date_deadline = self.date_deadline
calendar = self._get_warehouse_calendar()
return sale_line_model._expedition_date_from_delivery_date(
date_deadline - timedelta(days=7), # TODO: we don't know the start of the date range
date_deadline,
delays,
calendar=calendar
)

def _get_warehouse_calendar(self):
self.ensure_one()
warehouse = self.location_id.get_warehouse()
return warehouse.calendar2_id or None

def _is_late_to_ship(self, next_expedition_date):
self.ensure_one()
expected_expedition_date = self._get_expected_expedition_date()
return next_expedition_date.date() > expected_expedition_date.date()

def _get_next_expedition_date(self, from_date):
self.ensure_one()
calendar = self._get_warehouse_calendar()
if calendar:
# plan_hours will return the same datetime if now is part of an attendance,
# otherwise the beginning of the next one.
# If the returned date is after the scheduled date, then we are late
# to ship, and we need to postpone the delivery dates of the moves.
return calendar.plan_hours(0, from_date, compute_leaves=True)
else:
return from_date

def _compute_expected_delivery_date(self):
"""Computes the expected delivery date.
Expand All @@ -58,29 +94,16 @@ def _compute_expected_delivery_date(self):
commitment_date > expected_date > date_done > scheduled_date
"""
now = fields.Datetime.now()
sale_line_model = self.env["sale.order.line"]
sol_model = self.env["sale.order.line"]
for record in self:
sale_order = record.sale_id
warehouse = record.location_id.get_warehouse()
delivery_date = record.date_deadline or record.date_done
calendar = warehouse.calendar2_id
if calendar:
# plan_hours will return the current attendance if now is part of one,
# otherwise the beginning of the next one.
# If the returned date is after the scheduled date, then we are late
# to ship.
# TODO: At some point, we might need a carrier cutoff or something.
next_expedition_date = calendar.plan_hours(0, now, compute_leaves=True)
else:
next_expedition_date = now
late_to_ship = next_expedition_date.date() > record.scheduled_date.date()
if late_to_ship:
delivery_datetime_aware = sale_line_model._add_delay(
next_expedition_date, 1, calendar=calendar
)
tz_string = record.partner_id.tz or "UTC"
delivery_date = sale_line_model._get_naive_date_from_datetime(
delivery_datetime_aware, tz_string
next_expedition_date = record._get_next_expedition_date(now)
if record._is_late_to_ship(next_expedition_date):
delays = record._get_delays()
partner = record.partner_id
calendar = record._get_warehouse_calendar()
delivery_date = sol_model._delivery_date_from_expedition_date(
next_expedition_date, partner, calendar, delays
)
record.expected_delivery_date = delivery_date

Expand Down Expand Up @@ -196,20 +219,11 @@ def get_cutoff_time(self):

def _create_backorder(self):
res = super()._create_backorder()
sol_model = self.env["sale.order.line"]
now = fields.Datetime.now()
for picking in res:
warehouse = picking.location_id.get_warehouse()
calendar = warehouse.calendar2_id
if calendar:
# plan_hours will return the same datetime if now is part of an attendance,
# otherwise the beginning of the next one.
# If the returned date is after the scheduled date, then we are late
# to ship, and we need to postpone the delivery dates of the moves.
next_expedition_date = calendar.plan_hours(0, now, compute_leaves=True)
else:
next_expedition_date = now
late_to_ship = next_expedition_date.date() > picking.scheduled_date.date()
if late_to_ship:
next_expedition_date = self._get_next_expedition_date(now)
if picking._is_late_to_ship(next_expedition_date):
for line in picking.move_lines:
dates = line._get_delivery_dates(from_date=now)
line.write(dates)
Expand Down
13 changes: 7 additions & 6 deletions sale_delivery_date/tests/test_backorder_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def _increase_so_line_qty(cls, qty):

def test_backorder_before_scheduled_date(self):
# If we want the backorder to be delivered this week, then it has to be
# created before monday's cutoff.
# If so, it will be delivered friday, at 06:00
# created before the planned expedition (THURSDAY)
# If so, scheduled date and date deadline won't be postponed.
with freeze_time(f"{THURSDAY} {BEFORE_CUTOFF_UTC}"):
backorder = self._create_backorder()
self.assertEqual(str(backorder.scheduled_date), f"{THURSDAY} {CUTOFF_UTC}")
Expand All @@ -83,10 +83,11 @@ def test_backorder_before_scheduled_date(self):
)

def test_backorder_after_scheduled_date(self):
# If we want the backorder to be delivered this week, then it has to be
# created before monday's cutoff.
# If so, it will be delivered friday, at 06:00
with freeze_time(f"{THURSDAY} {AFTER_CUTOFF_UTC}"):
# If we want the backorder to be delivered this week, it has to be created
# before the planned expedition(THURSDAY)
# Here, we're creating the backorder on FRIDAY, it should be postponed
# to next THURSDAY for preparation, and next FRIDAY for delivery
with freeze_time(f"{FRIDAY} {BEFORE_CUTOFF_UTC}"):
backorder = self._create_backorder()
self.assertEqual(str(backorder.scheduled_date), f"{NEXT_THURSDAY} {CUTOFF_UTC}")
self.assertEqual(
Expand Down
4 changes: 2 additions & 2 deletions sale_delivery_date/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def test_order_on_tuesday_after_cutoff(self):
self.assertEqual(str(picking.scheduled_date.date()), expected_work_start_date)
self.assertEqual(str(order.expected_date.date()), expected_delivery_date)

@freeze_time("2023-07-06 16:00:00")
@freeze_time("2023-07-06 15:00:00")
def test_order_after_cutoff_to_delivery_tomorrow(self):
# Let's say we can ask a guy in the warehouse to work on this order
# right now to be ready to deliver today.
Expand Down Expand Up @@ -207,7 +207,7 @@ def test_order_on_thursday_after_cutoff_late_commitment_date(self):
str(picking.expected_delivery_date.date()), "2023-07-07"
)

@freeze_time("2023-08-18 13:05:50")
@freeze_time("2023-08-18 13:05:50") # 15:05:50 Europe/Brussels
def test_friday_order_with_commitment_date(self):
order = self.order_warehouse_cutoff
commitment_date = "2023-08-23"
Expand Down

0 comments on commit 11783a5

Please sign in to comment.