Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,5 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import test_rma
from . import test_rma_dashboard
from . import test_rma_operation

View file

@ -0,0 +1,928 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import Command
from odoo.exceptions import UserError, ValidationError
from odoo.tests import Form, new_test_user, tagged, users
from odoo.tools import mute_logger
from odoo.addons.base.tests.common import BaseCommon
from .. import hooks
class TestRma(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
if not cls.env.company.chart_template_id:
# Load a CoA if there's none in current company
coa = cls.env.ref("l10n_generic_coa.configurable_chart_template", False)
if not coa:
# Load the first available CoA
coa = cls.env["account.chart.template"].search(
[("visible", "=", True)], limit=1
)
coa.try_loading(company=cls.env.company, install_demo=False)
cls.user_rma = new_test_user(
cls.env,
login="user_rma",
groups="rma.rma_group_user_own,stock.group_stock_user",
)
cls.res_partner = cls.env["res.partner"]
cls.product_product = cls.env["product.product"]
cls.company = cls.env.user.company_id
cls.warehouse_company = cls.env["stock.warehouse"].search(
[("company_id", "=", cls.company.id)], limit=1
)
cls.rma_loc = cls.warehouse_company.rma_loc_id
cls.product = cls.product_product.create(
{"name": "Product test 1", "type": "product"}
)
cls.product_2 = cls.product_product.create(
{"name": "Product test 2", "type": "product"}
)
cls.account_receiv = cls.env["account.account"].create(
{
"name": "Receivable",
"code": "RCV00",
"account_type": "asset_receivable",
"reconcile": True,
}
)
cls.partner = cls.res_partner.create(
{
"name": "Partner test",
"property_account_receivable_id": cls.account_receiv.id,
"property_payment_term_id": cls.env.ref(
"account.account_payment_term_30days"
).id,
}
)
cls.partner_invoice = cls.res_partner.create(
{
"name": "Partner invoice test",
"parent_id": cls.partner.id,
"type": "invoice",
}
)
cls.partner_shipping = cls.res_partner.create(
{
"name": "Partner shipping test",
"parent_id": cls.partner.id,
"type": "delivery",
}
)
cls.finalization_reason_1 = cls.env["rma.finalization"].create(
{"name": ("[Test] It can't be repaired and customer doesn't want it")}
)
cls.finalization_reason_2 = cls.env["rma.finalization"].create(
{"name": "[Test] It's out of warranty. To be scrapped"}
)
cls.env.ref("rma.group_rma_manual_finalization").users |= cls.env.user
cls.warehouse = cls.env.ref("stock.warehouse0")
# Ensure grouping
cls.env.company.rma_return_grouping = True
cls.operation = cls.env.ref("rma.rma_operation_replace")
def _create_rma(
self, partner=None, product=None, qty=None, location=None, operation=None
):
vals = {}
if partner:
vals["partner_id"] = partner.id
if product:
vals["product_id"] = product.id
if qty:
vals["product_uom_qty"] = qty
if location:
vals["location_id"] = location.id
if operation:
vals["operation_id"] = operation.id
elif operation is None:
vals["operation_id"] = self.operation.id
return self.env["rma"].create(vals)
def _create_confirm_receive(
self, partner=None, product=None, qty=None, location=None, operation=None
):
rma = self._create_rma(partner, product, qty, location, operation)
rma.action_confirm()
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
return rma
def _receive_and_replace(self, partner, product, qty, location):
rma = self._create_confirm_receive(partner, product, qty, location)
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="replace",
)
)
delivery_form.product_id = rma.product_id
delivery_form.product_uom_qty = qty
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
return rma
def _create_delivery(self):
picking_type = self.env["stock.picking.type"].search(
[
("code", "=", "outgoing"),
"|",
("warehouse_id.company_id", "=", self.company.id),
("warehouse_id", "=", False),
],
limit=1,
)
picking_form = Form(
recordp=self.env["stock.picking"].with_context(
default_picking_type_id=picking_type.id
),
view="stock.view_picking_form",
)
picking_form.partner_id = self.partner
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product
move.product_uom_qty = 10
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product_product.create(
{"name": "Product 2 test", "type": "product"}
)
move.product_uom_qty = 20
picking = picking_form.save()
picking.action_confirm()
for move in picking.move_ids:
move.quantity_done = move.product_uom_qty
picking.button_validate()
return picking
@tagged("-at_install", "post_install")
class TestRmaCase(TestRma):
def test_post_init_hook(self):
warehouse = self.env["stock.warehouse"].create(
{
"name": "Test warehouse",
"code": "code",
"company_id": self.env.company.id,
}
)
hooks.post_init_hook(self.env.cr, self.registry)
self.assertTrue(warehouse.rma_in_type_id)
self.assertEqual(
warehouse.rma_in_type_id.default_location_dest_id, warehouse.rma_loc_id
)
self.assertEqual(
warehouse.rma_out_type_id.default_location_src_id, warehouse.rma_loc_id
)
self.assertTrue(warehouse.rma_loc_id)
self.assertTrue(warehouse.rma_in_route_id)
self.assertTrue(warehouse.rma_out_route_id)
def test_rma_replace_pick_ship(self):
self.warehouse.write({"delivery_steps": "pick_ship"})
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma.action_confirm()
rma.reception_move_id.quantity_done = 1
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.reception_move_id.picking_id.state, "done")
self.assertEqual(rma.state, "received")
res = rma.action_replace()
wizard_form = Form(self.env[res["res_model"]].with_context(**res["context"]))
wizard_form.product_id = self.product
wizard_form.product_uom_qty = rma.product_uom_qty
wizard = wizard_form.save()
wizard.action_deliver()
self.assertEqual(rma.delivery_picking_count, 2)
out_pickings = rma.mapped("delivery_move_ids.picking_id")
self.assertIn(
self.warehouse.pick_type_id, out_pickings.mapped("picking_type_id")
)
self.assertIn(
self.warehouse.out_type_id, out_pickings.mapped("picking_type_id")
)
def test_computed(self):
# If partner changes, the invoice address is set
rma = self.env["rma"].new()
rma.partner_id = self.partner
self.assertEqual(rma.partner_invoice_id, self.partner_invoice)
# If origin move changes, the product is set
uom_ten = self.env["uom.uom"].create(
{
"name": "Ten",
"category_id": self.env.ref("uom.product_uom_unit").id,
"factor_inv": 10,
"uom_type": "bigger",
}
)
product_2 = self.product_product.create(
{"name": "Product test 2", "type": "product", "uom_id": uom_ten.id}
)
outgoing_picking_type = self.env["stock.picking.type"].search(
[
("code", "=", "outgoing"),
"|",
("warehouse_id.company_id", "=", self.company.id),
("warehouse_id", "=", False),
],
limit=1,
)
picking_form = Form(
recordp=self.env["stock.picking"].with_context(
default_picking_type_id=outgoing_picking_type.id
),
view="stock.view_picking_form",
)
picking_form.partner_id = self.partner
with picking_form.move_ids_without_package.new() as move:
move.product_id = product_2
move.product_uom_qty = 15
picking = picking_form.save()
picking._action_done()
rma.picking_id = picking
rma.move_id = picking.move_ids
self.assertEqual(rma.product_id, product_2)
self.assertEqual(rma.product_uom_qty, 15)
self.assertEqual(rma.product_uom, uom_ten)
# If product changes, unit of measure changes
rma.move_id = False
rma.product_id = self.product
self.assertEqual(rma.product_uom, self.product.uom_id)
def test_ensure_required_fields_on_confirm(self):
rma = self._create_rma(operation=False)
with self.assertRaises(ValidationError) as e:
rma.action_confirm()
self.assertEqual(
e.exception.args[0],
"Required field(s):\nCustomer\nShipping Address\nInvoice Address\nProduct"
"\nRequested operation",
)
rma.partner_id = self.partner.id
with self.assertRaises(ValidationError) as e:
rma.action_confirm()
self.assertEqual(
e.exception.args[0], "Required field(s):\nProduct\nRequested operation"
)
rma.product_id = self.product.id
rma.location_id = self.rma_loc.id
with self.assertRaises(ValidationError) as e:
rma.action_confirm()
self.assertEqual(e.exception.args[0], "Required field(s):\nRequested operation")
rma.operation_id = self.operation
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
def test_confirm_and_receive(self):
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.reception_move_id.picking_id.state, "assigned")
self.assertEqual(rma.reception_move_id.product_id, rma.product_id)
self.assertEqual(rma.reception_move_id.product_uom_qty, 10)
self.assertEqual(rma.reception_move_id.product_uom, rma.product_uom)
self.assertEqual(rma.state, "confirmed")
rma.reception_move_id.quantity_done = 9
with self.assertRaises(ValidationError):
rma.reception_move_id.picking_id._action_done()
rma.reception_move_id.quantity_done = 10
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.reception_move_id.picking_id.state, "done")
self.assertEqual(rma.reception_move_id.quantity_done, 10)
self.assertEqual(rma.state, "received")
def test_cancel(self):
# cancel a draft RMA
rma = self._create_rma(self.partner, self.product)
rma.action_cancel()
self.assertEqual(rma.state, "cancelled")
# cancel a confirmed RMA
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
rma.action_cancel()
self.assertEqual(rma.state, "cancelled")
# A RMA is only cancelled from draft and confirmed states
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
with self.assertRaises(UserError):
rma.action_cancel()
def test_lock_unlock(self):
# A RMA is only locked from 'received' state
rma_1 = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma_2 = self._create_confirm_receive(
self.partner, self.product, 10, self.rma_loc
)
self.assertEqual(rma_1.state, "draft")
self.assertEqual(rma_2.state, "received")
(rma_1 | rma_2).action_lock()
self.assertEqual(rma_1.state, "draft")
self.assertEqual(rma_2.state, "locked")
# A RMA is only unlocked from 'lock' state and it will be set
# to 'received' state
(rma_1 | rma_2).action_unlock()
self.assertEqual(rma_1.state, "draft")
self.assertEqual(rma_2.state, "received")
@users("__system__", "user_rma")
def test_action_refund(self):
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
self.assertEqual(rma.state, "received")
self.assertTrue(rma.can_be_refunded)
self.assertTrue(rma.can_be_returned)
self.assertTrue(rma.can_be_replaced)
rma.action_refund()
self.assertEqual(rma.refund_id.move_type, "out_refund")
self.assertEqual(rma.refund_id.state, "draft")
self.assertFalse(rma.refund_id.invoice_payment_term_id)
self.assertEqual(rma.refund_line_id.product_id, rma.product_id)
self.assertEqual(rma.refund_line_id.quantity, 10)
self.assertEqual(rma.refund_line_id.product_uom_id, rma.product_uom)
self.assertEqual(rma.state, "refunded")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
# A regular user can create the refund but only Invoicing users will be able
# to edit it and post it
if self.env.user.login != "__system__":
return
with Form(rma.refund_line_id.move_id) as refund_form:
with refund_form.invoice_line_ids.edit(0) as refund_line:
refund_line.quantity = 9
with self.assertRaises(ValidationError):
rma.refund_id.action_post()
with Form(rma.refund_line_id.move_id) as refund_form:
with refund_form.invoice_line_ids.edit(0) as refund_line:
refund_line.quantity = 10
rma.refund_id.action_post()
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
def test_mass_refund(self):
# Create, confirm and receive rma_1
rma_1 = self._create_confirm_receive(
self.partner, self.product, 10, self.rma_loc
)
# create, confirm and receive 3 more RMAs
# rma_2: Same partner and same product as rma_1
rma_2 = self._create_confirm_receive(
self.partner, self.product, 15, self.rma_loc
)
# rma_3: Same partner and different product than rma_1
product = self.product_product.create(
{"name": "Product 2 test", "type": "product"}
)
rma_3 = self._create_confirm_receive(self.partner, product, 20, self.rma_loc)
# rma_4: Different partner and same product as rma_1
partner = self.res_partner.create(
{
"name": "Partner 2 test",
"property_account_receivable_id": self.account_receiv.id,
"company_id": self.company.id,
}
)
rma_4 = self._create_confirm_receive(partner, product, 25, self.rma_loc)
# all rmas are ready to refund
all_rmas = rma_1 | rma_2 | rma_3 | rma_4
self.assertEqual(all_rmas.mapped("state"), ["received"] * 4)
self.assertEqual(all_rmas.mapped("can_be_refunded"), [True] * 4)
# Mass refund of those four RMAs
action = self.env.ref("rma.rma_refund_action_server")
ctx = dict(self.env.context)
ctx.update(active_ids=all_rmas.ids, active_model="rma")
action.with_context(**ctx).run()
# After that all RMAs are in 'refunded' state
self.assertEqual(all_rmas.mapped("state"), ["refunded"] * 4)
# Two refunds were created
refund_1 = (rma_1 | rma_2 | rma_3).mapped("refund_id")
refund_2 = rma_4.refund_id
self.assertEqual(len(refund_1), 1)
self.assertEqual(len(refund_2), 1)
self.assertEqual((refund_1 | refund_2).mapped("state"), ["draft"] * 2)
# One refund per partner
self.assertNotEqual(refund_1.partner_id, refund_2.partner_id)
self.assertEqual(
refund_1.partner_id,
(rma_1 | rma_2 | rma_3).mapped("partner_invoice_id"),
)
self.assertEqual(refund_2.partner_id, rma_4.partner_invoice_id)
# Each RMA (rma_1, rma_2 and rma_3) is linked with a different
# line of refund_1
self.assertEqual(len(refund_1.invoice_line_ids), 3)
self.assertEqual(
refund_1.invoice_line_ids.rma_id,
(rma_1 | rma_2 | rma_3),
)
self.assertEqual(
(rma_1 | rma_2 | rma_3).mapped("refund_line_id"),
refund_1.invoice_line_ids,
)
# rma_4 is linked with the unique line of refund_2
self.assertEqual(len(refund_2.invoice_line_ids), 1)
self.assertEqual(refund_2.invoice_line_ids.rma_id, rma_4)
self.assertEqual(rma_4.refund_line_id, refund_2.invoice_line_ids)
# Assert product and quantities are propagated correctly
for rma in all_rmas:
self.assertEqual(rma.product_id, rma.refund_line_id.product_id)
self.assertEqual(rma.product_uom_qty, rma.refund_line_id.quantity)
self.assertEqual(rma.product_uom, rma.refund_line_id.product_uom_id)
# Less quantity -> error on confirm
with Form(rma_2.refund_line_id.move_id) as refund_form:
with refund_form.invoice_line_ids.edit(1) as refund_line:
refund_line.quantity = 14
with self.assertRaises(ValidationError):
refund_1.action_post()
with Form(rma_2.refund_line_id.move_id) as refund_form:
with refund_form.invoice_line_ids.edit(1) as refund_line:
refund_line.quantity = 15
refund_1.action_post()
refund_2.action_post()
def test_replace(self):
# Create, confirm and receive an RMA
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
# Replace with another product with quantity 2.
product_2 = self.product_product.create(
{"name": "Product 2 test", "type": "product"}
)
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="replace",
)
)
delivery_form.product_id = product_2
delivery_form.product_uom_qty = 2
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
self.assertEqual(len(rma.delivery_move_ids.picking_id.move_ids), 1)
self.assertEqual(rma.delivery_move_ids.product_id, product_2)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 2)
self.assertTrue(rma.delivery_move_ids.picking_id.state, "waiting")
self.assertEqual(rma.state, "waiting_replacement")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertTrue(rma.can_be_replaced)
self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
first_move = rma.delivery_move_ids
picking = first_move.picking_id
# Replace again with another product with the remaining quantity
product_3 = self.product_product.create(
{"name": "Product 3 test", "type": "product"}
)
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="replace",
)
)
delivery_form.product_id = product_3
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
second_move = rma.delivery_move_ids - first_move
self.assertEqual(len(rma.delivery_move_ids), 2)
self.assertEqual(rma.delivery_move_ids.mapped("picking_id"), picking)
self.assertEqual(first_move.product_id, product_2)
self.assertEqual(first_move.product_uom_qty, 2)
self.assertEqual(second_move.product_id, product_3)
self.assertEqual(second_move.product_uom_qty, 8)
self.assertTrue(picking.state, "waiting")
self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
# remaining_qty is 0 but rma is not set to 'replaced' until
# remaining_qty_to_done is less than or equal to 0
first_move.quantity_done = 2
second_move.quantity_done = 8
picking.button_validate()
self.assertEqual(picking.state, "done")
self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 10)
self.assertEqual(rma.remaining_qty_to_done, 0)
# The RMA is now in 'replaced' state
self.assertEqual(rma.state, "replaced")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
# Despite being in 'replaced' state,
# RMAs can still perform replacements.
self.assertTrue(rma.can_be_replaced)
def test_return_to_customer(self):
# Create, confirm and receive an RMA
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
# Return the same product with quantity 2 to the customer.
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="return",
)
)
delivery_form.product_uom_qty = 2
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
picking = rma.delivery_move_ids.picking_id
self.assertEqual(len(picking.move_ids), 1)
self.assertEqual(rma.delivery_move_ids.product_id, self.product)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 2)
self.assertTrue(picking.state, "waiting")
self.assertEqual(rma.state, "waiting_return")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_replaced)
self.assertTrue(rma.can_be_returned)
self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
first_move = rma.delivery_move_ids
picking = first_move.picking_id
# Validate the picking
first_move.quantity_done = 2
picking.button_validate()
self.assertEqual(picking.state, "done")
self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 2)
self.assertEqual(rma.remaining_qty_to_done, 8)
# Return the remaining quantity to the customer
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="return",
)
)
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
second_move = rma.delivery_move_ids - first_move
second_move.quantity_done = 8
self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 2)
self.assertEqual(rma.remaining_qty_to_done, 8)
self.assertEqual(rma.state, "waiting_return")
# remaining_qty is 0 but rma is not set to 'returned' until
# remaining_qty_to_done is less than or equal to 0
picking_2 = second_move.picking_id
picking_2.button_validate()
self.assertEqual(picking_2.state, "done")
self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 10)
self.assertEqual(rma.remaining_qty_to_done, 0)
# The RMA is now in 'returned' state
self.assertEqual(rma.state, "returned")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
def test_finish_rma(self):
# Create, confirm and receive an RMA
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
rma.action_finish()
finalization_form = Form(
self.env["rma.finalization.wizard"].with_context(
active_ids=rma.ids,
rma_finalization_type="replace",
)
)
finalization_form.finalization_id = self.finalization_reason_2
finalization_wizard = finalization_form.save()
finalization_wizard.action_finish()
self.assertEqual(rma.state, "finished")
self.assertEqual(rma.finalization_id, self.finalization_reason_2)
def test_mass_return_to_customer(self):
# Create, confirm and receive rma_1
rma_1 = self._create_confirm_receive(
self.partner, self.product, 10, self.rma_loc
)
# create, confirm and receive 3 more RMAs
# rma_2: Same partner and same product as rma_1
rma_2 = self._create_confirm_receive(
self.partner, self.product, 15, self.rma_loc
)
# rma_3: Same partner and different product than rma_1
product = self.product_product.create(
{"name": "Product 2 test", "type": "product"}
)
rma_3 = self._create_confirm_receive(self.partner, product, 20, self.rma_loc)
# rma_4: Different partner and same product as rma_1
partner = self.res_partner.create({"name": "Partner 2 test"})
rma_4 = self._create_confirm_receive(partner, product, 25, self.rma_loc)
# all rmas are ready to be returned to the customer
all_rmas = rma_1 | rma_2 | rma_3 | rma_4
self.assertEqual(all_rmas.mapped("state"), ["received"] * 4)
self.assertEqual(all_rmas.mapped("can_be_returned"), [True] * 4)
all_in_pickings = all_rmas.mapped("reception_move_id.picking_id")
self.assertEqual(
all_in_pickings.mapped("picking_type_id"), self.warehouse.rma_in_type_id
)
self.assertEqual(
all_in_pickings.mapped("location_dest_id"), self.warehouse.rma_loc_id
)
# Mass return of those four RMAs
delivery_wizard = (
self.env["rma.delivery.wizard"]
.with_context(active_ids=all_rmas.ids, rma_delivery_type="return")
.create({})
)
delivery_wizard.action_deliver()
# Two pickings were created
pick_1 = (rma_1 | rma_2 | rma_3).mapped("delivery_move_ids.picking_id")
pick_2 = rma_4.delivery_move_ids.picking_id
self.assertEqual(pick_1.picking_type_id, self.warehouse.rma_out_type_id)
self.assertEqual(pick_1.location_id, self.warehouse.rma_loc_id)
self.assertEqual(pick_2.picking_type_id, self.warehouse.rma_out_type_id)
self.assertEqual(pick_2.location_id, self.warehouse.rma_loc_id)
self.assertEqual(len(pick_1), 1)
self.assertEqual(len(pick_2), 1)
self.assertNotEqual(pick_1, pick_2)
self.assertEqual((pick_1 | pick_2).mapped("state"), ["assigned"] * 2)
# One picking per partner
self.assertNotEqual(pick_1.partner_id, pick_2.partner_id)
self.assertEqual(
pick_1.partner_id,
(rma_1 | rma_2 | rma_3).mapped("partner_shipping_id"),
)
self.assertEqual(pick_2.partner_id, rma_4.partner_id)
# Each RMA of (rma_1, rma_2 and rma_3) is linked to a different
# line of picking_1
self.assertEqual(len(pick_1.move_ids), 3)
self.assertEqual(
pick_1.move_ids.rma_id,
(rma_1 | rma_2 | rma_3),
)
self.assertEqual(
(rma_1 | rma_2 | rma_3).mapped("delivery_move_ids"),
pick_1.move_ids,
)
# rma_4 is linked with the unique move of pick_2
self.assertEqual(len(pick_2.move_ids), 1)
self.assertEqual(pick_2.move_ids.rma_id, rma_4)
self.assertEqual(rma_4.delivery_move_ids, pick_2.move_ids)
# Assert product and quantities are propagated correctly
for rma in all_rmas:
self.assertEqual(rma.product_id, rma.delivery_move_ids.product_id)
self.assertEqual(rma.product_uom_qty, rma.delivery_move_ids.product_uom_qty)
self.assertEqual(rma.product_uom, rma.delivery_move_ids.product_uom)
rma.delivery_move_ids.quantity_done = rma.product_uom_qty
pick_1.button_validate()
pick_2.button_validate()
self.assertEqual(all_rmas.mapped("state"), ["returned"] * 4)
def test_mass_return_to_customer_ungrouped(self):
"""We can choose to avoid the customer returns grouping"""
self.env.company.rma_return_grouping = False
# Create, confirm and receive rma_1
rma_1 = self._create_confirm_receive(
self.partner, self.product, 10, self.rma_loc
)
# create, confirm and receive 3 more RMAs
# rma_2: Same partner and same product as rma_1
rma_2 = self._create_confirm_receive(
self.partner, self.product, 15, self.rma_loc
)
# rma_3: Same partner and different product than rma_1
product = self.product_product.create(
{"name": "Product 2 test", "type": "product"}
)
rma_3 = self._create_confirm_receive(self.partner, product, 20, self.rma_loc)
# rma_4: Different partner and same product as rma_1
partner = self.res_partner.create({"name": "Partner 2 test"})
rma_4 = self._create_confirm_receive(partner, product, 25, self.rma_loc)
# all rmas are ready to be returned to the customer
all_rmas = rma_1 | rma_2 | rma_3 | rma_4
self.assertEqual(all_rmas.mapped("state"), ["received"] * 4)
self.assertEqual(all_rmas.mapped("can_be_returned"), [True] * 4)
# Mass return of those four RMAs
delivery_wizard = (
self.env["rma.delivery.wizard"]
.with_context(active_ids=all_rmas.ids, rma_delivery_type="return")
.create({})
)
delivery_wizard.action_deliver()
self.assertEqual(4, len(all_rmas.delivery_move_ids.picking_id))
def test_rma_from_picking_return(self):
# Create a return from a delivery picking
origin_delivery = self._create_delivery()
stock_return_picking_form = Form(
self.env["stock.return.picking"].with_context(
active_ids=origin_delivery.ids,
active_id=origin_delivery.id,
active_model="stock.picking",
)
)
stock_return_picking_form.create_rma = True
stock_return_picking_form.rma_operation_id = self.operation
return_wizard = stock_return_picking_form.save()
picking_action = return_wizard.create_returns()
# Each origin move is linked to a different RMA
origin_moves = origin_delivery.move_ids
self.assertTrue(origin_moves[0].rma_ids)
self.assertTrue(origin_moves[1].rma_ids)
rmas = origin_moves.rma_ids
self.assertEqual(rmas.mapped("state"), ["confirmed"] * 2)
# Each reception move is linked one of the generated RMAs
reception = self.env["stock.picking"].browse(picking_action["res_id"])
reception_moves = reception.move_ids
self.assertTrue(reception_moves[0].rma_receiver_ids)
self.assertTrue(reception_moves[1].rma_receiver_ids)
self.assertEqual(reception_moves.rma_receiver_ids, rmas)
# Validate the reception picking to set rmas to 'received' state
reception_moves[0].quantity_done = reception_moves[0].product_uom_qty
reception_moves[1].quantity_done = reception_moves[1].product_uom_qty
reception.button_validate()
self.assertEqual(rmas.mapped("state"), ["received"] * 2)
def test_split(self):
origin_delivery = self._create_delivery()
rma_form = Form(self.env["rma"])
rma_form.partner_id = self.partner
rma_form.picking_id = origin_delivery
rma_form.move_id = origin_delivery.move_ids.filtered(
lambda r: r.product_id == self.product
)
rma_form.operation_id = self.operation
rma = rma_form.save()
rma.action_confirm()
rma.reception_move_id.quantity_done = 10
rma.reception_move_id.picking_id._action_done()
# Return quantity 4 of the same product to the customer
delivery_form = Form(
self.env["rma.delivery.wizard"].with_context(
active_ids=rma.ids,
rma_delivery_type="return",
)
)
delivery_form.product_uom_qty = 4
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
rma.delivery_move_ids.quantity_done = 4
rma.delivery_move_ids.picking_id.button_validate()
self.assertEqual(rma.state, "waiting_return")
# Extract the remaining quantity to another RMA
self.assertTrue(rma.can_be_split)
split_wizard = (
self.env["rma.split.wizard"]
.with_context(
active_id=rma.id,
active_ids=rma.ids,
)
.create({})
)
action = split_wizard.action_split()
# Check rma is set to 'returned' after split. Check new_rma values
self.assertEqual(rma.state, "returned")
new_rma = self.env["rma"].browse(action["res_id"])
self.assertEqual(new_rma.origin_split_rma_id, rma)
self.assertEqual(new_rma.delivered_qty, 0)
self.assertEqual(new_rma.remaining_qty, 6)
self.assertEqual(new_rma.delivered_qty_done, 0)
self.assertEqual(new_rma.remaining_qty_to_done, 6)
self.assertEqual(new_rma.state, "received")
self.assertTrue(new_rma.can_be_refunded)
self.assertTrue(new_rma.can_be_returned)
self.assertTrue(new_rma.can_be_replaced)
self.assertEqual(new_rma.move_id, rma.move_id)
self.assertEqual(new_rma.reception_move_id, rma.reception_move_id)
self.assertEqual(new_rma.product_uom_qty + rma.product_uom_qty, 10)
self.assertEqual(new_rma.move_id.quantity_done, 10)
self.assertEqual(new_rma.reception_move_id.quantity_done, 10)
@mute_logger("odoo.models.unlink")
def test_rma_to_receive_on_delete_invoice(self):
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
rma.action_refund()
self.assertEqual(rma.state, "refunded")
rma.refund_id.unlink()
self.assertFalse(rma.refund_id)
self.assertEqual(rma.state, "received")
self.assertTrue(rma.can_be_refunded)
self.assertTrue(rma.can_be_returned)
self.assertTrue(rma.can_be_replaced)
def test_rma_picking_type_default_values(self):
warehouse = self.env["stock.warehouse"].create(
{"name": "Stock - RMA Test", "code": "SRT"}
)
self.assertFalse(warehouse.rma_in_type_id.use_create_lots)
self.assertTrue(warehouse.rma_in_type_id.use_existing_lots)
def test_quantities_on_hand(self):
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
self.assertEqual(rma.product_id.qty_available, 0)
def test_autoconfirm_email(self):
self.company.send_rma_confirmation = True
self.company.send_rma_receipt_confirmation = True
self.company.send_rma_draft_confirmation = True
self.company.rma_mail_confirmation_template_id = self.env.ref(
"rma.mail_template_rma_notification"
)
self.company.rma_mail_receipt_confirmation_template_id = self.env.ref(
"rma.mail_template_rma_receipt_notification"
)
self.company.rma_mail_draft_confirmation_template_id = self.env.ref(
"rma.mail_template_rma_draft_notification"
)
previous_mails = self.env["mail.mail"].search(
[("partner_ids", "in", self.partner.ids)]
)
self.assertFalse(previous_mails)
# Force the context to mock an RMA created from the portal, which is
# feature that we get on `rma_sale`. We drop it after the RMA creation
# to avoid uncontrolled side effects
ctx = self.env.context
self.env.context = dict(ctx, from_portal=True)
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.env.context = ctx
mail_draft = self.env["mail.message"].search(
[("partner_ids", "in", self.partner.ids)]
)
rma.action_confirm()
mail_confirm = (
self.env["mail.message"].search([("partner_ids", "in", self.partner.ids)])
- mail_draft
)
self.assertTrue(rma.name in mail_confirm.subject)
self.assertTrue(rma.name in mail_confirm.body)
self.assertEqual(
self.env.ref("rma.mt_rma_notification"), mail_confirm.subtype_id
)
# Now we'll confirm the incoming goods picking and the automatic
# reception notification should be sent
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id.button_validate()
mail_receipt = (
self.env["mail.message"].search([("partner_ids", "in", self.partner.ids)])
- mail_draft
- mail_confirm
)
self.assertTrue(rma.name in mail_receipt.subject)
self.assertTrue("products received" in mail_receipt.subject)
def test_replace_picking_type(self):
"""
Test that by default, the replace operation uses the default delivery route,
meaning the warehouse's default delivery picking type is applied.
RMA replacement orders are not separated from regular deliveries, and both use
the same picking type.
"""
rma = self._receive_and_replace(self.partner, self.product, 2, self.rma_loc)
rma_in_type = self.warehouse.rma_in_type_id
out_type = self.warehouse.out_type_id
self.assertEqual(rma.reception_move_id.picking_type_id, rma_in_type)
self.assertEqual(rma.delivery_move_ids.picking_type_id, out_type)
def test_replace_picking_type_custom_picking_type(self):
"""
Test that when configured to use a custom route, the replace operation uses a
custom picking type, separating RMA replacement orders from regular deliveries.
The custom picking type is applied specifically for RMA replacements, instead
of the default delivery picking type.
"""
rma_in_type = self.warehouse.rma_in_type_id
rma_out_type = self.warehouse.rma_out_type_id
route = self.env["stock.route"].create(
{
"name": "RMA OUT replace",
"active": True,
"sequence": 100,
"product_selectable": True,
"rule_ids": [
Command.create(
{
"name": "RMA OUT",
"action": "pull",
"picking_type_id": rma_out_type.id,
"location_src_id": self.warehouse.lot_stock_id.id,
"location_dest_id": self.env.ref(
"stock.stock_location_customers"
).id,
},
)
],
}
)
self.warehouse.rma_out_replace_route_id = route
rma = self._receive_and_replace(self.partner, self.product, 2, self.rma_loc)
self.assertEqual(rma.reception_move_id.picking_type_id, rma_in_type)
self.assertEqual(rma.delivery_move_ids.picking_type_id, rma_out_type)
def test_grouping_reception_enabled(self):
rma_1 = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma_2 = self._create_rma(self.partner, self.product_2, 10, self.rma_loc)
(rma_1 | rma_2).action_confirm()
self.assertEqual(
rma_1.reception_move_id.picking_id, rma_2.reception_move_id.picking_id
)

View file

@ -0,0 +1,73 @@
# Copyright 2024 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from .test_rma import TestRma
PROCESSED_STATES = ["received", "refunded", "replaced", "finished"]
AWAITING_ACTION_STATES = ["waiting_return", "waiting_replacement", "confirmed"]
class TestRmaDashboard(TestRma):
def test_0(self):
operation_replace = self.env.ref("rma.rma_operation_replace")
operation_return = self.env.ref("rma.rma_operation_return")
operation_refund = self.env.ref("rma.rma_operation_refund")
replace_draft_1 = self._create_rma(
self.partner, self.product, 1, self.rma_loc, operation=operation_replace
)
self._create_rma(
self.partner, self.product, 1, self.rma_loc, operation=operation_replace
) # replace_draft_2
replace_draft_1.copy({"state": "confirmed"}) # replace_confirmed
replace_draft_1.copy({"state": "received"}) # replace_received
replace_draft_1.copy({"state": "waiting_return"}) # replace_waiting_return
replace_draft_1.copy( # replace_waiting_replacement
{"state": "waiting_replacement"}
)
return_draft = self._create_rma(
self.partner, self.product, 1, self.rma_loc, operation=operation_return
)
return_draft.copy({"state": "confirmed"}) # return_confirmed
return_draft.copy({"state": "waiting_return"}) # return_waiting_return
return_draft.copy({"state": "returned"}) # return_returned
return_draft.copy({"state": "finished"}) # return_finished
refund_draft = self._create_rma(
self.partner, self.product, 1, self.rma_loc, operation=operation_refund
)
refund_draft.copy({"state": "finished"}) # refund_refunded
self.assertEqual(operation_replace.count_rma_draft, 2)
self.assertEqual(operation_replace.count_rma_awaiting_action, 3)
self.assertEqual(operation_replace.count_rma_processed, 1)
self.assertEqual(operation_return.count_rma_draft, 1)
self.assertEqual(operation_return.count_rma_awaiting_action, 2)
self.assertEqual(operation_return.count_rma_processed, 1)
self.assertEqual(operation_refund.count_rma_draft, 1)
self.assertEqual(operation_refund.count_rma_awaiting_action, 0)
self.assertEqual(operation_refund.count_rma_processed, 1)
action = operation_replace.get_action_rma_tree_draft()
self.assertListEqual(
["&", ("operation_id", "=", operation_replace.id), ("state", "=", "draft")],
action.get("domain"),
)
action = operation_replace.get_action_rma_tree_awaiting_action()
self.assertListEqual(
[
"&",
("operation_id", "=", operation_replace.id),
("state", "in", AWAITING_ACTION_STATES),
],
action.get("domain"),
)
action = operation_replace.get_action_rma_tree_processed()
self.assertListEqual(
[
"&",
("operation_id", "=", operation_replace.id),
("state", "in", PROCESSED_STATES),
],
action.get("domain"),
)

View file

@ -0,0 +1,335 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.exceptions import ValidationError
from odoo.tests.common import Form
from .test_rma import TestRma
class TestRmaOperation(TestRma):
def test_01(self):
"""
ensure that the receipt creation behaves correctly according to the
action_create_receipt setting.
- "automatic_on_confirm":
- receipts are created automatically
- the manual button is hidden
- "manual_on_confirm"
- manual button is visible after confirmation
- disappears once a receipt is manually created
"""
self.assertEqual(self.operation.action_create_receipt, "automatic_on_confirm")
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.show_create_receipt)
rma.action_confirm()
self.assertTrue(rma.reception_move_id)
self.assertFalse(rma.show_create_receipt)
self.operation.action_create_receipt = "manual_on_confirm"
rma2 = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma2.action_confirm()
self.assertTrue(rma2.show_create_receipt)
self.assertFalse(rma2.reception_move_id)
rma2.action_create_receipt()
self.assertFalse(rma2.show_create_receipt)
def test_02(self):
"""
test delivery button visibility based on operation settings.
No deliver possible
"""
self.operation.action_create_delivery = False
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.show_create_return)
self.assertFalse(rma.can_be_replaced)
self.assertFalse(rma.show_create_replace)
def test_03(self):
"""
test delivery button visibility based on operation settings.
deliver manually after confirm
"""
self.operation.action_create_delivery = "manual_on_confirm"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertTrue(rma.can_be_returned)
self.assertTrue(rma.show_create_return)
self.assertTrue(rma.can_be_replaced)
self.assertTrue(rma.show_create_replace)
def test_04(self):
"""
test delivery button visibility based on operation settings.
deliver automatically after confirm, return same product
"""
self.operation.action_create_delivery = "automatic_on_confirm"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
rma.action_confirm()
self.assertEqual(rma.state, "waiting_replacement")
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.show_create_return)
self.assertFalse(rma.can_be_replaced)
self.assertFalse(rma.show_create_replace)
self.assertTrue(rma.delivery_move_ids)
self.assertEqual(rma.delivery_move_ids.product_id, self.product)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 10)
def test_05(self):
"""
test delivery button visibility based on operation settings.
deliver manually after receipt
"""
self.operation.action_create_delivery = "manual_after_receipt"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.show_create_return)
self.assertFalse(rma.can_be_replaced)
self.assertFalse(rma.show_create_replace)
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.state, "received")
self.assertTrue(rma.can_be_returned)
self.assertTrue(rma.show_create_return)
self.assertTrue(rma.can_be_replaced)
self.assertTrue(rma.show_create_replace)
def test_06(self):
"""
test delivery button visibility based on operation settings.
deliver automatically after receipt
"""
self.operation.action_create_delivery = "automatic_after_receipt"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.show_create_return)
self.assertFalse(rma.can_be_replaced)
self.assertFalse(rma.show_create_replace)
self.assertFalse(rma.delivery_move_ids)
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.delivery_move_ids.product_id, self.product)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 10)
self.assertEqual(rma.state, "waiting_replacement")
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.show_create_return)
self.assertTrue(rma.can_be_replaced)
self.assertFalse(rma.show_create_replace)
def test_07(self):
"""
test delivery button visibility based on operation settings.
deliver automatically after confirm, different product
"""
self.operation.action_create_delivery = "automatic_on_confirm"
self.operation.different_return_product = True
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
with self.assertRaises(AssertionError, msg="Replacement fields are required"):
with Form(rma) as rma_form:
rma_form.save()
with self.assertRaises(
ValidationError, msg="Complete the replacement information"
):
rma.action_confirm()
rma.return_product_id = self.product_product.create(
{"name": "return Product test 1", "type": "product"}
)
rma.action_confirm()
self.assertEqual(rma.delivery_move_ids.product_id, rma.product_id)
self.assertEqual(rma.reception_move_id.product_id, rma.return_product_id)
self.assertEqual(rma.state, "waiting_replacement")
def test_08(self):
"""test refund, manually after confirm"""
self.operation.action_create_refund = "manual_on_confirm"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertTrue(rma.can_be_refunded)
self.assertTrue(rma.show_create_refund)
def test_09(self):
"""test refund, manually after receipt"""
self.operation.action_create_refund = "manual_after_receipt"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.show_create_refund)
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.state, "received")
self.assertTrue(rma.can_be_refunded)
self.assertTrue(rma.show_create_refund)
def test_10(self):
"""test refund, automatic after confirm"""
self.operation.action_create_refund = "automatic_on_confirm"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "refunded")
self.assertTrue(rma.refund_id)
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.show_create_refund)
def test_11(self):
"""test refund, automatic after confirm"""
self.operation.action_create_refund = "automatic_after_receipt"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.state, "refunded")
self.assertTrue(rma.refund_id)
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.show_create_refund)
def test_12(self):
"""
Refund without product return
Some companies may offer refunds without requiring the return of the product,
often in cases of low-value items or when the cost of return shipping is
prohibitive.
- no receipt
- no return
- automatically refund on confirm
"""
self.operation.action_create_receipt = False
self.operation.action_create_refund = "automatic_on_confirm"
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "refunded")
self.assertFalse(rma.reception_move_id)
self.assertTrue(rma.refund_id)
def test_13(self):
"""
Return of non-ordered product
Occasionally, customers receive items they did not order and need a process for
returning these products. The delivered product don't figure on the sale order
- receipt
- no return
- no refund
"""
self.operation.action_create_receipt = "automatic_on_confirm"
self.operation.action_create_delivery = False
self.operation.action_create_refund = False
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.state, "received")
self.assertFalse(rma.delivery_move_ids)
def test_14(self):
"""if the refund action is not ment to update quantity, return picking line
to_refund field should be False"""
self.operation.action_create_refund = "manual_after_receipt"
origin_delivery = self._create_delivery()
stock_return_picking_form = Form(
self.env["stock.return.picking"].with_context(
active_ids=origin_delivery.ids,
active_id=origin_delivery.id,
active_model="stock.picking",
)
)
stock_return_picking_form.create_rma = True
stock_return_picking_form.rma_operation_id = self.operation
return_wizard = stock_return_picking_form.save()
return_line = return_wizard.product_return_moves.filtered(
lambda m, p=self.product: m.product_id == p
)
self.assertEqual(return_line.rma_operation_id, self.operation)
picking_action = return_wizard.create_returns()
reception = self.env["stock.picking"].browse(picking_action["res_id"])
move = reception.move_ids.filtered(lambda m, p=self.product: m.product_id == p)
self.assertFalse(move.to_refund)
def test_15(self):
"""if the refund action is ment to update quantity, return picking line
to_refund field should be True"""
self.operation.action_create_refund = "update_quantity"
origin_delivery = self._create_delivery()
stock_return_picking_form = Form(
self.env["stock.return.picking"].with_context(
active_ids=origin_delivery.ids,
active_id=origin_delivery.id,
active_model="stock.picking",
)
)
stock_return_picking_form.create_rma = True
stock_return_picking_form.rma_operation_id = self.operation
return_wizard = stock_return_picking_form.save()
return_line = return_wizard.product_return_moves.filtered(
lambda m, p=self.product: m.product_id == p
)
self.assertEqual(return_line.rma_operation_id, self.operation)
picking_action = return_wizard.create_returns()
reception = self.env["stock.picking"].browse(picking_action["res_id"])
move = reception.move_ids.filtered(lambda m, p=self.product: m.product_id == p)
self.assertTrue(move.to_refund)
def test_rma_replace_pick_ship(self):
self.operation.action_create_delivery = "automatic_on_confirm"
self.warehouse.write({"delivery_steps": "pick_ship"})
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.state, "waiting_replacement")
out_pickings = rma.mapped("delivery_move_ids.picking_id")
self.assertEqual(rma.delivery_picking_count, 2)
self.assertIn(
self.warehouse.pick_type_id, out_pickings.mapped("picking_type_id")
)
self.assertIn(
self.warehouse.out_type_id, out_pickings.mapped("picking_type_id")
)
def test_16(self):
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.reception_move_id.state, "assigned")
self.assertEqual(rma.reception_move_id.picking_id.state, "assigned")
def test_17(self):
self.operation.auto_confirm_reception = True
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma.action_confirm()
self.assertEqual(rma.reception_move_id.state, "done")
self.assertEqual(rma.reception_move_id.picking_id.state, "done")
def test_manual_finish_if_no_required_action_flag(self):
self.operation.action_create_receipt = False
self.operation.action_create_delivery = False
self.operation.action_create_refund = False
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma.action_confirm()
self.assertFalse(rma.requires_action)
self.assertEqual(rma.state, "confirmed")
rma.action_finish()
self.assertEqual(rma.state, "finished")
self.operation.action_create_receipt = "manual_on_confirm"
rma2 = self._create_rma(self.partner, self.product, 1, self.rma_loc)
rma2.action_confirm()
self.assertTrue(rma2.requires_action)
self.assertEqual(rma2.state, "confirmed")
with self.assertRaises(ValidationError):
rma2.action_finish()