# Copyright 2020 Tecnativa - Ernesto Tejeda # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.tests import Form, SavepointCase from odoo.exceptions import UserError, ValidationError class TestRma(SavepointCase): @classmethod def setUpClass(cls): super(TestRma, cls).setUpClass() 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 account_pay = cls.env['account.account'].create({ 'code': 'X1111', 'name': 'Creditors - (test)', 'user_type_id': cls.env.ref( 'account.data_account_type_payable').id, 'reconcile': True, }) cls.journal = cls.env['account.journal'].create({ 'name': 'sale_0', 'code': 'SALE0', 'type': 'sale', 'default_debit_account_id': account_pay.id, }) cls.product = cls.product_product.create({ 'name': 'Product test 1', 'type': 'product', }) account_type = cls.env['account.account.type'].create({ 'name': 'RCV type', 'type': 'receivable', }) cls.account_receiv = cls.env['account.account'].create({ 'name': 'Receivable', 'code': 'RCV00', 'user_type_id': account_type.id, 'reconcile': True, }) cls.partner = cls.res_partner.create({ 'name': 'Partner test', 'property_account_receivable_id': cls.account_receiv.id, }) cls.partner_invoice = cls.res_partner.create({ 'name': 'Partner invoice test', 'parent_id': cls.partner.id, 'type': 'invoice', }) def _create_rma(self, partner=None, product=None, qty=None, location=None): rma_form = Form(self.env['rma']) if partner: rma_form.partner_id = partner if product: rma_form.product_id = product if qty: rma_form.product_uom_qty = qty if location: rma_form.location_id = location return rma_form.save() def _create_confirm_receive(self, partner=None, product=None, qty=None, location=None): rma = self._create_rma(partner, product, qty, location) rma.action_confirm() rma.reception_move_id.quantity_done = rma.product_uom_qty rma.reception_move_id.picking_id.action_done() return rma def _test_readonly_fields(self, rma): with Form(rma) as rma_form: with self.assertRaises(AssertionError): rma_form.partner_id = self.env['res.partner'] with self.assertRaises(AssertionError): rma_form.partner_invoice_id = self.env['res.partner'] with self.assertRaises(AssertionError): rma_form.picking_id = self.env['stock.picking'] with self.assertRaises(AssertionError): rma_form.move_id = self.env['stock.move'] with self.assertRaises(AssertionError): rma_form.product_id = self.env['product.product'] with self.assertRaises(AssertionError): rma_form.product_uom_qty = 0 with self.assertRaises(AssertionError): rma_form.product_uom = self.env['uom.uom'] with self.assertRaises(AssertionError): rma_form.location_id = self.env['stock.location'] 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.company_id = self.company 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_lines: move.quantity_done = move.product_uom_qty picking.button_validate() return picking def test_onchange(self): rma_form = Form(self.env['rma']) # If partner changes, the invoice address is set rma_form.partner_id = self.partner self.assertEqual(rma_form.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.company_id = self.company picking_form.partner_id = self.partner 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 move.product_uom = uom_ten picking = picking_form.save() picking.action_done() rma_form.picking_id = picking rma_form.move_id = picking.move_lines self.assertEqual(rma_form.product_id, product_2) self.assertEqual(rma_form.product_uom_qty, 15) self.assertEqual(rma_form.product_uom, uom_ten) # If product changes, unit of measure changes rma_form.picking_id = self.env['stock.picking'] rma_form.product_id = self.product self.assertEqual(rma_form.product_id, self.product) self.assertEqual(rma_form.product_uom_qty, 15) self.assertNotEqual(rma_form.product_uom, uom_ten) self.assertEqual(rma_form.product_uom, self.product.uom_id) rma = rma_form.save() # If product changes, unit of measure domain should also change domain = rma._onchange_product_id()['domain']['product_uom'] self.assertListEqual( domain, [('category_id', '=', self.product.uom_id.category_id.id)]) def test_ensure_required_fields_on_confirm(self): rma = self._create_rma() with self.assertRaises(ValidationError) as e: rma.action_confirm() self.assertEqual( e.exception.name, "Required field(s):\nCustomer\nInvoice Address\nProduct\nLocation" ) with Form(rma) as rma_form: rma_form.partner_id = self.partner with self.assertRaises(ValidationError) as e: rma.action_confirm() self.assertEqual( e.exception.name, "Required field(s):\nProduct\nLocation") with Form(rma) as rma_form: rma_form.product_id = self.product rma_form.location_id = self.rma_loc 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') self._test_readonly_fields(rma) 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') self._test_readonly_fields(rma) def test_cancel(self): # cancel a draft RMA rma = self._create_rma(self.partner, self.product) rma.action_cancel() self.assertEqual(rma.state, 'cancelled') self._test_readonly_fields(rma) # 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') 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.type, 'out_refund') self.assertEqual(rma.refund_id.state, 'draft') 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.uom_id, rma.product_uom) self.assertEqual(rma.state, 'waiting_refund') self.assertFalse(rma.can_be_refunded) self.assertFalse(rma.can_be_returned) self.assertFalse(rma.can_be_replaced) rma.refund_line_id.quantity = 9 with self.assertRaises(ValidationError): rma.refund_id.action_invoice_open() rma.refund_line_id.quantity = 10 rma.refund_id.action_invoice_open() self.assertEqual(rma.state, 'refunded') self.assertFalse(rma.can_be_refunded) self.assertFalse(rma.can_be_returned) self.assertFalse(rma.can_be_replaced) self._test_readonly_fields(rma) 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() # 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.mapped('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.uom_id) # Less quantity -> error on confirm rma_2.refund_line_id.quantity = 14 with self.assertRaises(ValidationError): refund_1.action_invoice_open() rma_2.refund_line_id.quantity = 15 refund_1.action_invoice_open() refund_2.action_invoice_open() self.assertEqual(all_rmas.mapped('state'), ['refunded']*4) 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_lines), 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) self._test_readonly_fields(rma) 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_lines), 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) self._test_readonly_fields(rma) 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) # 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(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_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_lines), 3) self.assertEqual( pick_1.move_lines.mapped('rma_id'), (rma_1 | rma_2 | rma_3), ) self.assertEqual( (rma_1 | rma_2 | rma_3).mapped('delivery_move_ids'), pick_1.move_lines, ) # rma_4 is linked with the unique move of pick_2 self.assertEqual(len(pick_2.move_lines), 1) self.assertEqual(pick_2.move_lines.rma_id, rma_4) self.assertEqual(rma_4.delivery_move_ids, pick_2.move_lines) # 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_rma_from_picking_return(self): # Create a return from a delivery picking origin_delivery = self._create_delivery() return_wizard = self.env['stock.return.picking'].with_context( active_id=origin_delivery.id, active_ids=origin_delivery.ids, ).create({'create_rma': True}) picking_action = return_wizard.create_returns() # Each origin move is linked to a different RMA origin_moves = origin_delivery.move_lines self.assertTrue(origin_moves[0].rma_ids) self.assertTrue(origin_moves[1].rma_ids) rmas = origin_moves.mapped('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_lines self.assertTrue(reception_moves[0].rma_receiver_ids) self.assertTrue(reception_moves[1].rma_receiver_ids) self.assertEqual(reception_moves.mapped('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_lines.filtered( lambda r: r.product_id == self.product) 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)