Skip to content

Commit

Permalink
[IMP] sale_order_line_cancel: support kits
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaudoux authored and rousseldenis committed Jun 28, 2024
1 parent 483041b commit 736014a
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 23 deletions.
3 changes: 2 additions & 1 deletion sale_order_line_cancel/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# © 2016 Sylvain Van Hoof
# Copyright 2018 Sylvain Van Hoof (Okia SPRL)
# Copyright 2018 Jacques-Etienne Baudoux (BCIM) <[email protected]>
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

Expand Down
38 changes: 31 additions & 7 deletions sale_order_line_cancel/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Copyright 2018 Okia SPRL
# Copyright 2018 Jacques-Etienne Baudoux (BCIM) <[email protected]>
# Copyright 2020 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, fields, models
from odoo import _, api, fields, models
from odoo.tools import float_compare


Expand Down Expand Up @@ -34,7 +35,7 @@ def _compute_can_cancel_remaining_qty(self):
)
== 1
and rec.state in ("sale", "done")
and rec.move_ids
and rec.qty_delivered_method == "stock_move"
)

@api.depends(
Expand All @@ -44,10 +45,33 @@ def _compute_can_cancel_remaining_qty(self):
)
def _compute_product_qty_remains_to_deliver(self):
for line in self:
remaining_to_deliver = (
line.product_uom_qty - line.qty_delivered - line.product_qty_canceled
)
line.product_qty_remains_to_deliver = remaining_to_deliver
qty_remaining = line.qty_to_deliver - line.product_qty_canceled
line.product_qty_remains_to_deliver = qty_remaining

def _get_moves_to_cancel(self):
return self.move_ids.filtered(lambda m: m.state not in ("done", "cancel"))

def _check_moves_to_cancel(self, moves):
"""override this method to add checks before cancel"""
"""Override this method to add checks before cancel"""
self.ensure_one()

def _update_qty_canceled(self):
"""Update SO line qty canceled only when all remaining moves are canceled"""
for line in self:
if line._get_moves_to_cancel():
continue
line.product_qty_canceled = line.qty_to_deliver

def cancel_remaining_qty(self):
lines = self.filtered(lambda l: l.can_cancel_remaining_qty)
for line in lines:
moves_to_cancel = line._get_moves_to_cancel()
line._check_moves_to_cancel(moves_to_cancel)
moves_to_cancel._action_cancel()
line.order_id.message_post(
body=_(
"<b>%(product)s</b>: The order line has been canceled",
product=line.product_id.display_name,
)
)
return True
15 changes: 11 additions & 4 deletions sale_order_line_cancel/models/stock_move.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2023 ACSONE SA/NV
# Copyright 2024 Jacques-Etienne Baudoux (BCIM) <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import models
Expand All @@ -13,8 +14,14 @@ def _action_cancel(self):
lambda m: m.sale_line_id and m.state not in ("done", "cancel")
)
res = super()._action_cancel()
for rec in sale_moves:
if rec.state != "cancel":
continue
rec.sale_line_id.product_qty_canceled = rec.product_uom_qty
sale_lines = sale_moves.filtered(lambda m: m.state == "cancel").sale_line_id
sale_lines._update_qty_canceled()
return res

def _action_done(self, cancel_backorder=False):
moves_todo = super()._action_done(cancel_backorder=cancel_backorder)
if cancel_backorder and moves_todo:
# _action_cancel is called before marking as done, so the hook on
# _action_cancel will not be triggered. Call it now
self.sale_line_id._update_qty_canceled()
return moves_todo
19 changes: 19 additions & 0 deletions sale_order_line_cancel/tests/test_sale_order_line_cancel.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ def test_cancel_pickings(self):
active_id=self.sale.order_line.id, active_model="sale.order.line"
).cancel_remaining_qty()

def test_cancel_move_kit(self):
"""when all remaining moves are canceled product_qty_canceled increased"""
self.assertTrue(self.sale.order_line.can_cancel_remaining_qty)
move = self.sale.picking_ids.move_ids
self.assertEqual(move.sale_line_id, self.sale.order_line)
# simulate a kit with a second move linked to the sale SO line
move2 = move.copy()
move2._action_confirm()
self.assertEqual(move2.sale_line_id, self.sale.order_line)
move._action_cancel()
self.assertEqual(self.sale.order_line.product_qty_canceled, 0)
move2._action_cancel()
self.assertEqual(self.sale.order_line.product_qty_canceled, 10)
self.assertEqual(self.sale.order_line.product_qty_remains_to_deliver, 0)
self.assertFalse(self.sale.order_line.can_cancel_remaining_qty)
self.wiz.with_context(
active_id=self.sale.order_line.id, active_model="sale.order.line"
).cancel_remaining_qty()

def test_reset_to_draft(self):
ship = self.sale.picking_ids
ship.action_assign()
Expand Down
12 changes: 1 addition & 11 deletions sale_order_line_cancel/wizards/sale_order_line_cancel.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,5 @@ def _get_moves_to_cancel(self, line):

def cancel_remaining_qty(self):
line = self._get_sale_order_line()
if not line.can_cancel_remaining_qty:
return False
cancel_moves = self._get_moves_to_cancel(line)
line._check_moves_to_cancel(cancel_moves)
cancel_moves._action_cancel()
line.order_id.message_post(
body=_(
"<b>%(product)s</b>: The order line has been canceled",
product=line.product_id.display_name,
)
)
line.cancel_remaining_qty()
return True

0 comments on commit 736014a

Please sign in to comment.