Skip to content

Commit

Permalink
[16.0][FIX] rma, add support to handle package used on customer moves
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisOForgeFlow authored and PauBForgeFlow committed Mar 8, 2024
1 parent 3c0e9c4 commit d0df9bf
Show file tree
Hide file tree
Showing 9 changed files with 475 additions and 16 deletions.
1 change: 1 addition & 0 deletions rma/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
from . import res_partner
from . import res_company
from . import res_config_settings
from . import stock_package_level
4 changes: 4 additions & 0 deletions rma/models/rma_order_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ def _default_date_rma(self):
string="Under Warranty?", readonly=True, states={"draft": [("readonly", False)]}
)

def _get_stock_move_reference(self):
self.ensure_one()
return self.reference_move_id

def _prepare_rma_line_from_stock_move(self, sm, lot=False):
if not self.type:
self.type = self._get_default_type()
Expand Down
13 changes: 13 additions & 0 deletions rma/models/stock_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,16 @@ def _update_reserved_quantity(
def _prepare_merge_moves_distinct_fields(self):
res = super()._prepare_merge_moves_distinct_fields()
return res + ["rma_line_id"]


class StockMoveLine(models.Model):

_inherit = "stock.move.line"

def _should_bypass_reservation(self, location):
res = super(StockMoveLine, self)._should_bypass_reservation(location)
if self.env.context.get(
"force_no_bypass_reservation"
) and location.usage not in ("customer", "supplier"):
return False
return res
20 changes: 20 additions & 0 deletions rma/models/stock_package_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from odoo import models


class StockPackageLevel(models.Model):

_inherit = "stock.package_level"

def write(self, values):
ctx = self.env.context.copy()
if (
len(self) == 1
and "location_dest_id" in values
and self.location_dest_id.id == values.get("location_dest_id")
):
ctx.update(
{
"bypass_reservation_update": True,
}
)
return super(StockPackageLevel, self.with_context(**ctx)).write(values)
210 changes: 202 additions & 8 deletions rma/tests/test_rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def setUpClass(cls):
cls.make_supplier_rma = cls.env["rma.order.line.make.supplier.rma"]
cls.rma_add_stock_move = cls.env["rma_add_stock_move"]
cls.product_ctg_model = cls.env["product.category"]
cls.lot_obj = cls.env["stock.production.lot"]
cls.package_obj = cls.env["stock.quant.package"]
cls.stockpicking = cls.env["stock.picking"]
cls.rma = cls.env["rma.order"]
cls.rma_line = cls.env["rma.order.line"]
Expand All @@ -31,6 +33,8 @@ def setUpClass(cls):
)
cls.product_id = cls._create_product("PT0")
cls.product_1 = cls._create_product("PT1")
cls.product_1_serial = cls._create_product("PT1 Serial", "serial")
cls.product_1_lot = cls._create_product("PT1 Lot", "lot")
cls.product_2 = cls._create_product("PT2")
cls.product_3 = cls._create_product("PT3")
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
Expand Down Expand Up @@ -146,9 +150,14 @@ def _create_product_category(
)

@classmethod
def _create_product(cls, name):
def _create_product(cls, name, tracking="none"):
return cls.product_product_model.create(
{"name": name, "categ_id": cls.category.id, "type": "product"}
{
"name": name,
"categ_id": cls.category.id,
"type": "product",
"tracking": tracking,
}
)

@classmethod
Expand All @@ -174,7 +183,7 @@ def _do_picking(cls, picking):
picking.button_validate()

@classmethod
def _create_inventory(cls, product, qty, location):
def _create_inventory(cls, product, qty, location, lot_id=False, package_id=False):
"""
Creates inventory of a product on a specific location, this will be used
eventually to create a inventory at specific cost, that will be received in
Expand All @@ -187,6 +196,8 @@ def _create_inventory(cls, product, qty, location):
"location_id": location.id,
"product_id": product.id,
"inventory_quantity": qty,
"prod_lot_id": lot_id,
"package_id": package_id,
}
)
.action_apply_inventory()
Expand Down Expand Up @@ -231,13 +242,21 @@ def _create_rma_from_move(
for item in products2move:
product = item[0]
product_qty = item[1]
cls._create_inventory(product, product_qty, cls.stock_location)
lot_id = len(item) >= 3 and item[2] or False
origin_package_id = len(item) >= 4 and item[3] or False
destination_package_id = len(item) >= 5 and item[4] or False
cls._create_inventory(
product, product_qty, cls.stock_location, lot_id, origin_package_id
)
move_values = cls._prepare_move(
product,
product_qty,
cls.stock_location,
cls.customer_location,
picking,
lot_id,
origin_package_id=origin_package_id,
destination_package_id=destination_package_id,
)
moves.append(cls.env["stock.move"].create(move_values))
else:
Expand All @@ -248,13 +267,21 @@ def _create_rma_from_move(
for item in products2move:
product = item[0]
product_qty = item[1]
cls._create_inventory(product, product_qty, cls.stock_location)
lot_id = len(item) >= 3 and item[2] or False
origin_package_id = len(item) >= 4 and item[3] or False
destination_package_id = len(item) >= 5 and item[4] or False
cls._create_inventory(
product, product_qty, cls.stock_location, lot_id, origin_package_id
)
move_values = cls._prepare_move(
product,
product_qty,
cls.supplier_location,
cls.stock_rma_location,
picking,
lot_id,
origin_package_id=origin_package_id,
destination_package_id=destination_package_id,
)
moves.append(cls.env["stock.move"].create(move_values))
# Process the picking
Expand Down Expand Up @@ -290,7 +317,9 @@ def _create_rma_from_move(
data = (
wizard.with_user(cls.rma_basic_user)
.with_context(customer=1)
._prepare_rma_line_from_stock_move(move)
._prepare_rma_line_from_stock_move(
move, lot=len(move.lot_ids) == 1 and move.lot_ids[0] or False
)
)

else:
Expand Down Expand Up @@ -332,10 +361,20 @@ def _create_rma_from_move(
return rma_id

@classmethod
def _prepare_move(cls, product, qty, src, dest, picking_in):
def _prepare_move(
cls,
product,
qty,
src,
dest,
picking_in,
lot_id=False,
origin_package_id=False,
destination_package_id=False,
):
location_id = src.id

return {
res = {
"name": product.name,
"partner_id": picking_in.partner_id.id,
"origin": picking_in.name,
Expand All @@ -349,6 +388,29 @@ def _prepare_move(cls, product, qty, src, dest, picking_in):
"picking_id": picking_in.id,
"price_unit": product.standard_price,
}
if lot_id or origin_package_id or destination_package_id:
res.update(
{
"move_line_ids": [
(
0,
0,
{
"picking_id": picking_in.id,
"product_id": product.id,
"product_uom_id": product.uom_id.id,
"qty_done": qty,
"lot_id": lot_id,
"package_id": origin_package_id,
"result_package_id": destination_package_id,
"location_id": location_id,
"location_dest_id": dest.id,
},
)
]
}
)
return res

def _check_equal_quantity(self, qty1, qty2, msg):
self.assertEqual(qty1, qty2, msg)
Expand Down Expand Up @@ -1083,3 +1145,135 @@ def test_08_supplier_rma_single_line(self):
self.assertTrue(partner, "Partner is not defined or False")
moves = picking.move_ids
self.assertEqual(len(moves), 1, "Incorrect number of moves created")

def test_10_customer_rma_tracking_lot(self):
lot = self.lot_obj.create(
{
"product_id": self.product_1_lot.id,
}
)
origin_package = self.package_obj.create({})
destination_package = self.package_obj.create({})
products2move = [
(self.product_1_lot, 5, lot.id, origin_package.id, destination_package.id)
]
rma_customer_id = self._create_rma_from_move(
products2move,
"customer",
self.env.ref("base.res_partner_2"),
dropship=False,
)
rma = rma_customer_id.rma_line_ids
rma.action_rma_to_approve()
wizard = self.rma_make_picking.with_context(
**{
"active_ids": rma.ids,
"active_model": "rma.order.line",
"picking_type": "incoming",
"active_id": rma.ids[0],
}
).create({})
wizard.action_create_picking()
res = rma.action_view_in_shipments()
self.assertTrue("res_id" in res, "Incorrect number of pickings" "created")
picking = self.env["stock.picking"].browse(res["res_id"])
self.assertEqual(len(picking), 1, "Incorrect number of pickings created")
moves = picking.move_lines
self.assertEqual(
destination_package,
moves.mapped("move_line_ids.package_id"),
"Should have same package assigned",
)
self.assertFalse(
bool(moves.mapped("move_line_ids.result_package_id")),
"Destination package should not be assigned",
)
picking.action_assign()
for mv in picking.move_lines:
mv.quantity_done = mv.product_uom_qty
picking._action_done()
wizard = self.rma_make_picking.with_context(
**{
"active_id": rma.ids[0],
"active_ids": rma.ids,
"active_model": "rma.order.line",
"picking_type": "outgoing",
}
).create({})
wizard.action_create_picking()
res = rma.action_view_out_shipments()
picking = self.env["stock.picking"].browse(res["res_id"])
picking.action_assign()
for mv in picking.move_lines:
mv.quantity_done = mv.product_uom_qty
picking._action_done()
self.assertEqual(picking.state, "done", "Final picking should has done state")

def test_11_customer_rma_tracking_serial(self):
lot = self.lot_obj.create(
{
"product_id": self.product_1_serial.id,
}
)
origin_package = self.package_obj.create({})
destination_package = self.package_obj.create({})
products2move = [
(
self.product_1_serial,
1,
lot.id,
origin_package.id,
destination_package.id,
)
]
rma_customer_id = self._create_rma_from_move(
products2move,
"customer",
self.env.ref("base.res_partner_2"),
dropship=False,
)
rma = rma_customer_id.rma_line_ids
rma.action_rma_to_approve()
wizard = self.rma_make_picking.with_context(
**{
"active_ids": rma.ids,
"active_model": "rma.order.line",
"picking_type": "incoming",
"active_id": rma.ids[0],
}
).create({})
wizard.action_create_picking()
res = rma.action_view_in_shipments()
self.assertTrue("res_id" in res, "Incorrect number of pickings" "created")
picking = self.env["stock.picking"].browse(res["res_id"])
self.assertEqual(len(picking), 1, "Incorrect number of pickings created")
moves = picking.move_lines
self.assertEqual(
destination_package,
moves.mapped("move_line_ids.package_id"),
"Should have same package assigned",
)
self.assertFalse(
bool(moves.mapped("move_line_ids.result_package_id")),
"Destination package should not be assigned",
)
picking.action_assign()
for mv in picking.move_lines:
mv.quantity_done = mv.product_uom_qty
picking._action_done()
wizard = self.rma_make_picking.with_context(
**{
"active_id": rma.ids[0],
"active_ids": rma.ids,
"active_model": "rma.order.line",
"picking_type": "outgoing",
}
).create({})
wizard.action_create_picking()
res = rma.action_view_out_shipments()
picking = self.env["stock.picking"].browse(res["res_id"])
picking.action_assign()
for mv in picking.move_lines:
mv.quantity_done = mv.product_uom_qty
picking._action_done()
self.assertEqual(picking.state, "done", "Final picking should has done state")
Loading

0 comments on commit d0df9bf

Please sign in to comment.