# © 2017 ForgeFlow # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo.exceptions import UserError, ValidationError from odoo.tests import Form, common class TestRma(common.TransactionCase): """Test the routes and the quantities""" @classmethod def setUpClass(cls): super(TestRma, cls).setUpClass() # models cls.rma_make_picking = cls.env["rma_make_picking.wizard"] 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.stockpicking = cls.env["stock.picking"] cls.rma = cls.env["rma.order"] cls.rma_line = cls.env["rma.order.line"] cls.rma_op = cls.env["rma.operation"] cls.product_product_model = cls.env["product.product"] cls.res_users_model = cls.env["res.users"] # References and records cls.rma_cust_replace_op_id = cls.env.ref("rma.rma_operation_customer_replace") cls.rma_sup_replace_op_id = cls.env.ref("rma.rma_operation_supplier_replace") cls.rma_ds_replace_op_id = cls.env.ref("rma.rma_operation_ds_replace") cls.category = cls._create_product_category( "one_step", cls.rma_cust_replace_op_id, cls.rma_sup_replace_op_id ) cls.product_id = cls._create_product("PT0") cls.product_1 = cls._create_product("PT1") cls.product_2 = cls._create_product("PT2") cls.product_3 = cls._create_product("PT3") cls.uom_unit = cls.env.ref("uom.product_uom_unit") cls.company = cls.env.company cls.company.group_rma_delivery_address = True cls.company.group_rma_lines = True cls.partner_id = cls.env.ref("base.res_partner_2") cls.stock_location = cls.env.ref("stock.stock_location_stock") cls.wh = cls.env.ref("stock.warehouse0") cls.stock_rma_location = cls.wh.lot_rma_id cls.customer_location = cls.env.ref("stock.stock_location_customers") cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") cls.product_uom_id = cls.env.ref("uom.product_uom_unit") cls.g_rma_customer_user = cls.env.ref("rma.group_rma_customer_user") cls.g_rma_supplier_user = cls.env.ref("rma.group_rma_supplier_user") cls.g_rma_manager = cls.env.ref("rma.group_rma_manager") cls.g_stock_user = cls.env.ref("stock.group_stock_user") cls.g_stock_manager = cls.env.ref("stock.group_stock_manager") cls.rma_basic_user = cls._create_user( "rma worker", [cls.g_stock_user, cls.g_rma_customer_user, cls.g_rma_supplier_user], cls.company, ) cls.rma_manager_user = cls._create_user( "rma manager", [cls.g_stock_manager, cls.g_rma_manager], cls.company, ) # Customer RMA: products2move = [(cls.product_1, 3), (cls.product_2, 5), (cls.product_3, 2)] cls.rma_customer_id = cls._create_rma_from_move( products2move, "customer", cls.env.ref("base.res_partner_2"), dropship=False ) # Dropship: cls.rma_droship_id = cls._create_rma_from_move( products2move, "customer", cls.env.ref("base.res_partner_2"), dropship=True, supplier_address_id=cls.env.ref("base.res_partner_3"), ) # Supplier RMA: cls.rma_supplier_id = cls._create_rma_from_move( products2move, "supplier", cls.env.ref("base.res_partner_2"), dropship=False ) @classmethod def _create_user(cls, login, groups, company): group_ids = [group.id for group in groups] user = cls.res_users_model.create( { "name": login, "login": login, "email": "example@yourcompany.com", "company_id": company.id, "company_ids": [(4, company.id)], "groups_id": [(6, 0, group_ids)], } ) return user @classmethod def _receive_rma(cls, rma_line_ids): wizard = cls.rma_make_picking.with_context( **{ "active_ids": rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", "active_id": 1, } ).create({}) wizard._create_picking() res = rma_line_ids.action_view_in_shipments() picking = cls.env["stock.picking"].browse(res["res_id"]) picking.action_assign() for mv in picking.move_ids: mv.quantity_done = mv.product_uom_qty picking._action_done() return picking @classmethod def _deliver_rma(cls, rma_line_ids): wizard = cls.rma_make_picking.with_context( **{ "active_ids": rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "outgoing", "active_id": 1, } ).create({}) wizard._create_picking() res = rma_line_ids.action_view_out_shipments() picking = cls.env["stock.picking"].browse(res["res_id"]) picking.action_assign() for mv in picking.move_ids: mv.quantity_done = mv.product_uom_qty picking._action_done() return picking @classmethod def _create_product_category( cls, rma_approval_policy, rma_customer_operation_id, rma_supplier_operation_id ): return cls.product_ctg_model.create( { "name": "Test category", "rma_approval_policy": rma_approval_policy, "rma_customer_operation_id": rma_customer_operation_id.id, "rma_supplier_operation_id": rma_supplier_operation_id.id, } ) @classmethod def _create_product(cls, name): return cls.product_product_model.create( {"name": name, "categ_id": cls.category.id, "type": "product"} ) @classmethod def _create_picking(cls, partner, picking_type): return cls.stockpicking.create( { "partner_id": partner.id, "picking_type_id": picking_type.id, "location_id": cls.stock_location.id, "location_dest_id": cls.supplier_location.id, } ) @classmethod def _do_picking(cls, picking): """Do picking with only one move on the given date.""" picking.action_confirm() picking.action_assign() for ml in picking.move_ids: ml.filtered( lambda m: m.state != "waiting" ).quantity_done = ml.product_uom_qty picking.button_validate() @classmethod def _create_inventory(cls, product, qty, location): """ 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 a customer RMA or delivered in a supplier RMA """ inventory = ( cls.env["stock.quant"] .create( { "location_id": location.id, "product_id": product.id, "inventory_quantity": qty, } ) .action_apply_inventory() ) return inventory @classmethod def _get_picking_type(cls, wh, loc1, loc2): picking_type = cls.env["stock.picking.type"].search( [ ("warehouse_id", "=", wh.id), ("default_location_src_id", "=", loc1.id), ("default_location_dest_id", "=", loc2.id), ], limit=1, ) if picking_type: return picking_type picking_type = cls.env["stock.picking.type"].create( { "name": loc1.name + " to " + loc2.name, "sequence_code": loc1.name + " to " + loc2.name, "code": "incoming", "warehouse_id": wh.id, "default_location_src_id": loc1.id, "default_location_dest_id": loc2.id, } ) return picking_type @classmethod def _create_rma_from_move( cls, products2move, r_type, partner, dropship, supplier_address_id=None ): moves = [] if r_type == "customer": picking_type = cls._get_picking_type( cls.wh, cls.stock_location, cls.customer_location ) picking = cls._create_picking(partner, picking_type) for item in products2move: product = item[0] product_qty = item[1] cls._create_inventory(product, product_qty, cls.stock_location) move_values = cls._prepare_move( product, product_qty, cls.stock_location, cls.customer_location, picking, ) moves.append(cls.env["stock.move"].create(move_values)) else: picking_type = cls._get_picking_type( cls.wh, cls.supplier_location, cls.stock_rma_location ) picking = cls._create_picking(partner, picking_type) for item in products2move: product = item[0] product_qty = item[1] cls._create_inventory(product, product_qty, cls.stock_location) move_values = cls._prepare_move( product, product_qty, cls.supplier_location, cls.stock_rma_location, picking, ) moves.append(cls.env["stock.move"].create(move_values)) # Process the picking cls._do_picking(picking) # Create the RMA from the stock_move rma_id = cls.rma.with_user(cls.rma_basic_user).create( { "reference": "0001", "type": r_type, "partner_id": partner.id, "company_id": cls.env.ref("base.main_company").id, } ) for move in moves: if r_type == "customer": wizard = cls.rma_add_stock_move.with_user(cls.rma_basic_user).new( { "move_ids": [(4, move.id)], "rma_id": rma_id.id, "partner_id": move.partner_id.id, } ) wizard.with_context( **{ "move_ids": [(4, move.id)], "reference_move_id": move.id, "customer": True, "active_ids": rma_id.id, "partner_id": move.partner_id.id, "active_model": "rma.order", } ).default_get([str(move.id), str(cls.partner_id.id)]) data = ( wizard.with_user(cls.rma_basic_user) .with_context(customer=1) ._prepare_rma_line_from_stock_move(move) ) else: wizard = cls.rma_add_stock_move.with_user(cls.rma_basic_user).new( { "move_ids": [(4, move.id)], "rma_id": rma_id.id, "partner_id": move.partner_id.id, } ) wizard.with_context( **{ "move_ids": [(4, move.id)], "reference_move_id": move.id, "active_ids": rma_id.id, "partner_id": move.partner_id.id, "active_model": "rma.order", } ).default_get([str(move.id), str(cls.partner_id.id)]) data = wizard.with_user( cls.rma_basic_user )._prepare_rma_line_from_stock_move(move) data["type"] = "supplier" if dropship: data.update( customer_to_supplier=dropship, operation_id=cls.rma_ds_replace_op_id.id, supplier_address_id=supplier_address_id.id, ) cls.line = cls.rma_line.with_user(cls.rma_basic_user).create(data) cls.line._onchange_product_id() cls.line._onchange_operation_id() cls.line.action_rma_to_approve() rma_id._get_default_type() rma_id.action_view_in_shipments() rma_id.action_view_out_shipments() rma_id.action_view_lines() rma_id.partner_id.action_open_partner_rma() return rma_id @classmethod def _prepare_move(cls, product, qty, src, dest, picking_in): location_id = src.id return { "name": product.name, "partner_id": picking_in.partner_id.id, "origin": picking_in.name, "company_id": picking_in.picking_type_id.warehouse_id.company_id.id, "product_id": product.id, "product_uom": product.uom_id.id, "state": "draft", "product_uom_qty": qty, "location_id": location_id, "location_dest_id": dest.id, "picking_id": picking_in.id, "price_unit": product.standard_price, } def _check_equal_quantity(self, qty1, qty2, msg): self.assertEqual(qty1, qty2, msg) def test_01_rma_order_line(self): for line in self.rma_customer_id.rma_line_ids: line.with_context( **{"default_rma_id": line.rma_id.id} )._default_warehouse_id() line._default_location_id() line._onchange_delivery_address() line._compute_in_shipment_count() line._compute_out_shipment_count() # check assert if call reference_move_id onchange self.assertEqual(line.product_id, line.reference_move_id.product_id) self.assertEqual(line.product_qty, line.reference_move_id.product_uom_qty) self.assertEqual( line.location_id.location_id, line.reference_move_id.location_id ) self.assertEqual(line.origin, line.reference_move_id.picking_id.name) self.assertEqual( line.delivery_address_id, line.reference_move_id.picking_id.partner_id ) self.assertEqual( line.qty_to_receive, line.reference_move_id.product_uom_qty ) line._onchange_product_id() line._onchange_operation_id() # check assert if call operation_id onchange self.assertEqual(line.operation_id.receipt_policy, line.receipt_policy) data = {"customer_to_supplier": line.customer_to_supplier} line = self.rma_line.new(data) line._onchange_receipt_policy() data = {"lot_id": line.lot_id.id} line = self.rma_line.new(data) line._onchange_lot_id() line.action_view_in_shipments() line.action_view_out_shipments() self.rma_customer_id.action_view_supplier_lines() with self.assertRaises(ValidationError): line.rma_id.partner_id = self.partner_id.id self.rma_customer_id.rma_line_ids[0].partner_id = self.env.ref( "base.res_partner_3" ).id self.rma_customer_id.action_view_supplier_lines() def test_02_customer_rma(self): self.rma_customer_id.rma_line_ids.action_rma_to_approve() wizard = self.rma_make_picking.with_context( **{ "active_ids": self.rma_customer_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", "active_id": 1, } ).create({}) wizard._create_picking() res = self.rma_customer_id.rma_line_ids.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_ids self.assertEqual(len(moves), 3, "Incorrect number of moves created") lines = self.rma_customer_id.rma_line_ids lines.env.invalidate_all() self.assertEqual( list(set(lines.mapped("qty_received"))), [0], "Wrong qty received" ) self.assertEqual( list(set(lines.mapped("qty_to_deliver"))), [0], "Wrong qty to deliver" ) self.assertEqual( list(set(lines.mapped("qty_outgoing"))), [0], "Wrong qty outgoing" ) self.assertEqual( list(set(lines.mapped("qty_delivered"))), [0], "Wrong qty delivered" ) self.assertEqual( sum(lines.mapped("in_shipment_count")), 3, "Incorrect In Shipment Count" ) self.assertEqual( sum(lines.mapped("out_shipment_count")), 0, "Incorrect Out Shipment Count" ) self.assertEqual( self.rma_customer_id.in_shipment_count, 1, "Incorrect In Shipment Count" ) self.assertEqual( self.rma_customer_id.out_shipment_count, 0, "Incorrect Out Shipment Count" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_receive, 3, "Wrong qty to receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_incoming, 3, "Wrong qty incoming", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_receive, 5, "Wrong qty to receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_incoming, 5, "Wrong qty incoming", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_receive, 2, "Wrong qty to receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_incoming, 2, "Wrong qty incoming", ) picking.action_assign() for mv in picking.move_ids: mv.quantity_done = mv.product_uom_qty picking._action_done() lines = self.rma_customer_id.rma_line_ids self.assertEqual( list(set(lines.mapped("qty_to_receive"))), [0], "Wrong qty to_receive" ) self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty incoming" ) self.assertEqual( list(set(lines.mapped("qty_outgoing"))), [0], "Wrong qty outgoing" ) self.assertEqual( list(set(lines.mapped("qty_delivered"))), [0], "Wrong qty delivered" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_received, 3, "Wrong qty received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_deliver, 3, "Wrong qty to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_received, 5, "Wrong qty received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_deliver, 5, "Wrong qty to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_received, 2, "Wrong qty received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_deliver, 2, "Wrong qty to_deliver", ) wizard = self.rma_make_picking.with_context( **{ "active_id": 1, "active_ids": self.rma_customer_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "outgoing", } ).create({}) wizard._create_picking() res = self.rma_customer_id.rma_line_ids.action_view_out_shipments() self.assertTrue("res_id" in res, "Incorrect number of pickings" "created") picking = self.env["stock.picking"].browse(res["res_id"]) moves = picking.move_ids self.assertEqual(len(moves), 3, "Incorrect number of moves created") lines = self.rma_customer_id.rma_line_ids lines.env.invalidate_all() self.assertEqual( list(set(lines.mapped("qty_to_receive"))), [0], "Wrong qty to_receive" ) self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty incoming" ) self.assertEqual( list(set(lines.mapped("qty_delivered"))), [0], "Wrong qty delivered" ) self.assertEqual( sum(lines.mapped("in_shipment_count")), 3, "Incorrect In Shipment Count" ) self.assertEqual( sum(lines.mapped("out_shipment_count")), 3, "Incorrect Out Shipment Count", ) self.assertEqual( self.rma_customer_id.in_shipment_count, 1, "Incorrect In Shipment Count" ) self.assertEqual( self.rma_customer_id.out_shipment_count, 1, "Incorrect Out Shipment Count" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_deliver, 3, "Wrong qty to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_outgoing, 3, "Wrong qty outgoing", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_deliver, 5, "Wrong qty to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_outgoing, 5, "Wrong qty outgoing", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_deliver, 2, "Wrong qty to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_outgoing, 2, "Wrong qty outgoing", ) picking.action_assign() for mv in picking.move_ids: mv.quantity_done = mv.product_uom_qty picking._action_done() lines = self.rma_customer_id.rma_line_ids self.assertEqual( list(set(lines.mapped("qty_to_receive"))), [0], "Wrong qty to_receive" ) self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty incoming" ) self.assertEqual( list(set(lines.mapped("qty_outgoing"))), [0], "Wrong qty_outgoing" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_received, 3, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_delivered, 3, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_received, 5, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_delivered, 5, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_received, 2, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_delivered, 2, "Wrong qty_delivered", ) self.rma_customer_id.rma_line_ids.action_rma_done() self.assertEqual( self.rma_customer_id.rma_line_ids.mapped("state"), ["done", "done", "done"], "Wrong State", ) self.rma_customer_id.action_view_in_shipments() self.rma_customer_id.action_view_out_shipments() self.rma_customer_id.action_view_lines() # DROPSHIP def test_03_dropship(self): for line in self.rma_droship_id.rma_line_ids: line.operation_id = self.rma_ds_replace_op_id line._onchange_operation_id() line._onchange_delivery_address() line.action_rma_to_approve() line.action_rma_approve() wizard = self.rma_make_picking.with_context( **{ "active_id": 1, "active_ids": self.rma_droship_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", } ).create({}) wizard._create_picking() res = self.rma_droship_id.rma_line_ids.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_ids self.assertEqual(len(moves), 3, "Incorrect number of moves created") lines = self.rma_droship_id.rma_line_ids lines.env.invalidate_all() self.assertEqual( sum(lines.mapped("in_shipment_count")), 3, "Incorrect In Shipment Count" ) self.assertEqual( sum(lines.mapped("out_shipment_count")), 0, "Incorrect Out Shipment Count" ) self.assertEqual( self.rma_droship_id.in_shipment_count, 1, "Incorrect In Shipment Count" ) self.assertEqual( self.rma_droship_id.out_shipment_count, 0, "Incorrect Out Shipment Count" ) wizard = self.make_supplier_rma.with_context( **{ "active_ids": self.rma_droship_id.rma_line_ids.ids, "active_model": "rma.order.line", "active_id": 1, } ).create({}) wizard.make_supplier_rma() lines = self.rma_droship_id.rma_line_ids.mapped("supplier_rma_line_ids") lines.env.invalidate_all() self.assertEqual( list(set(lines.mapped("qty_received"))), [0], "Wrong qty_received" ) self.assertEqual( list(set(lines.mapped("qty_outgoing"))), [0], "Wrong qty_outgoing" ) self.assertEqual(list(set(lines.mapped("qty_delivered"))), [0], "qty_delivered") # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_deliver, 3, "Wrong qty_to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_deliver, 5, "Wrong qty_to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_deliver, 2, "Wrong qty_to_deliver", ) lines = self.rma_droship_id.rma_line_ids lines.env.invalidate_all() self._check_equal_quantity( lines.filtered( lambda l: l.product_id == self.product_1 ).qty_in_supplier_rma, 3, "Wrong qty_in_supplier_rma", ) self._check_equal_quantity( lines.filtered( lambda l: l.product_id == self.product_2 ).qty_in_supplier_rma, 5, "Wrong qty_in_supplier_rma", ) self._check_equal_quantity( lines.filtered( lambda l: l.product_id == self.product_3 ).qty_in_supplier_rma, 2, "Wrong qty_in_supplier_rma", ) self.assertEqual( list(set(lines.mapped("qty_to_supplier_rma"))), [0], "Wrong qty_to_supplier_rma", ) for line in self.rma_droship_id.rma_line_ids: line.action_rma_done() self.assertEqual(line.mapped("state"), ["done"], "Wrong State") # Supplier RMA def test_04_supplier_rma(self): self.rma_supplier_id.rma_line_ids.action_rma_to_approve() self.rma_supplier_id.rma_line_ids.operation_id = self.rma_sup_replace_op_id self.rma_supplier_id.rma_line_ids._onchange_operation_id() self.rma_supplier_id.rma_line_ids._onchange_delivery_address() wizard = self.rma_make_picking.with_context( **{ "active_ids": self.rma_supplier_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "outgoing", "active_id": 2, } ).create({}) wizard._create_picking() res = self.rma_supplier_id.rma_line_ids.action_view_out_shipments() self.assertTrue("res_id" in res, "Incorrect number of pickings" "created") picking = self.rma_supplier_id.rma_line_ids._get_out_pickings() partner = picking.partner_id self.assertTrue(partner, "Partner is not defined or False") moves = picking.move_ids self.assertEqual(len(moves), 3, "Incorrect number of moves created") lines = self.rma_supplier_id.rma_line_ids lines.env.invalidate_all() self.assertEqual( list(set(lines.mapped("qty_received"))), [0], "Wrong qty_received" ) self.assertEqual(list(set(lines.mapped("qty_delivered"))), [0], "qty_delivered") self.assertEqual( sum(lines.mapped("in_shipment_count")), 0, "Incorrect In Shipment Count" ) self.assertEqual( sum(lines.mapped("out_shipment_count")), 3, "Incorrect Out Shipment Count" ) self.assertEqual( self.rma_supplier_id.in_shipment_count, 0, "Incorrect In Shipment Count" ) self.assertEqual( self.rma_supplier_id.out_shipment_count, 1, "Incorrect Out Shipment Count" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_receive, 3, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_deliver, 3, "Wrong qty_to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_receive, 5, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_deliver, 5, "Wrong qty_to_deliver", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_receive, 2, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_deliver, 2, "Wrong qty_to_deliver", ) self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty_incoming" ) picking.action_assign() for mv in picking.move_ids: mv.quantity_done = mv.product_uom_qty picking._action_done() self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty_incoming" ) self.assertEqual( list(set(lines.mapped("qty_to_deliver"))), [0], "Wrong qty_to_deliver" ) self.assertEqual( list(set(lines.mapped("qty_received"))), [0], "Wrong qty_received" ) self.assertEqual(list(set(lines.mapped("qty_outgoing"))), [0], "qty_outgoing") # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_delivered, 3, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_receive, 3, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_received, 0, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_delivered, 5, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_received, 0, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_delivered, 2, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_received, 0, "Wrong qty_received", ) wizard = self.rma_make_picking.with_context( **{ "active_id": 1, "active_ids": self.rma_supplier_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", } ).create({}) wizard._create_picking() res = self.rma_supplier_id.rma_line_ids.action_view_in_shipments() self.assertTrue("res_id" in res, "Incorrect number of pickings" "created") pickings = self.env["stock.picking"].browse(res["res_id"]) self.assertEqual(len(pickings), 1, "Incorrect number of pickings created") picking_in = pickings[0] partner = picking_in.partner_id self.assertTrue(partner, "Partner is not defined or False") moves = picking.move_ids self.assertEqual(len(moves), 3, "Incorrect number of moves created") lines = self.rma_supplier_id.rma_line_ids lines.env.invalidate_all() self.assertEqual( list(set(lines.mapped("qty_to_deliver"))), [0], "qty_to_deliver" ) self.assertEqual( sum(lines.mapped("in_shipment_count")), 3, "Incorrect In Shipment Count" ) self.assertEqual( sum(lines.mapped("out_shipment_count")), 3, "Incorrect Out Shipment Count" ) self.assertEqual( self.rma_supplier_id.in_shipment_count, 1, "Incorrect In Shipment Count" ) self.assertEqual( self.rma_supplier_id.out_shipment_count, 1, "Incorrect Out Shipment Count" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_to_receive, 3, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_to_receive, 5, "Wrong qty_to_receive", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_to_receive, 2, "Wrong qty_to_receive", ) picking_in.action_confirm() picking_in.action_assign() for mv in picking_in.move_line_ids: mv.qty_done = mv.reserved_uom_qty picking_in._action_done() self.assertEqual( list(set(lines.mapped("qty_outgoing"))), [0], "Wrong qty_outgoing" ) self.assertEqual( list(set(lines.mapped("qty_incoming"))), [0], "Wrong qty_incoming" ) self.assertEqual( list(set(lines.mapped("qty_to_deliver"))), [0], "qty_to_deliver" ) # product specific self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_delivered, 3, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_1).qty_received, 3, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_delivered, 5, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_2).qty_received, 5, "Wrong qty_received", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_delivered, 2, "Wrong qty_delivered", ) self._check_equal_quantity( lines.filtered(lambda l: l.product_id == self.product_3).qty_received, 2, "Wrong qty_received", ) for line in self.rma_supplier_id.rma_line_ids: line.action_rma_done() self.assertEqual(line.state, "done", "Wrong State") def test_05_rma_order_line(self): """Property rma_customer_operation_id on product or product category correctly handled inside _onchange_product_id() """ rma_operation = self.env["rma.operation"].search([], limit=1) self.assertTrue(rma_operation) # Case of product template self.rma_customer_id.rma_line_ids.mapped("product_id").sudo().write( {"rma_customer_operation_id": rma_operation.id} ) for line in self.rma_customer_id.rma_line_ids: data = {"product_id": line.product_id.id} new_line = self.rma_line.new(data) self.assertFalse(new_line.operation_id) self.assertTrue(new_line.product_id.rma_customer_operation_id) self.assertTrue(new_line.product_id.categ_id.rma_customer_operation_id) new_line._onchange_product_id() self.assertEqual(new_line.operation_id, rma_operation) # Case of product category self.rma_customer_id.rma_line_ids.mapped("product_id").sudo().write( {"rma_customer_operation_id": False} ) self.rma_customer_id.rma_line_ids.mapped("product_id.categ_id").sudo().write( {"rma_customer_operation_id": rma_operation.id} ) for line in self.rma_customer_id.rma_line_ids: data = {"product_id": line.product_id.id} new_line = self.rma_line.new(data) self.assertFalse(new_line.operation_id) self.assertFalse(new_line.product_id.rma_customer_operation_id) self.assertTrue(new_line.product_id.categ_id.rma_customer_operation_id) new_line._onchange_product_id() self.assertEqual(new_line.operation_id, rma_operation) def test_06_warehouse_mismatch(self): """Mismatch between operation warehouse and stock rule warehouse is raised. * Create a second warehouse that is resupplied from the main warehouse * Update an RMA to receive into the second warehouse * When creating pickings, it is raised that the rules from the RMA * config are not used. """ wh2 = self.env["stock.warehouse"].create( { "name": "Shop.", "code": "SHP", } ) wh2.resupply_wh_ids = self.env.ref("stock.warehouse0") wh2.rma_in_this_wh = True wh2.lot_rma_id = self.env["stock.location"].create( { "name": "WH2 RMA", "usage": "internal", "location_id": wh2.lot_stock_id.id, } ) rma = self.rma_customer_id.copy() rma.rma_line_ids = self.rma_customer_id.rma_line_ids[0].copy() rma.rma_line_ids.product_id.sudo().route_ids += wh2.resupply_route_ids rma_form = Form(rma) rma_form.in_warehouse_id = wh2 rma_form.save() rma.rma_line_ids.action_rma_approve() wizard = self.rma_make_picking.with_context( **{ "active_ids": rma.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", "active_id": 1, } ).create({}) with self.assertRaisesRegex(UserError, "No rule found"): wizard._create_picking() def test_07_no_zero_qty_moves(self): rma_lines = self.rma_customer_id.rma_line_ids rma_lines.write({"receipt_policy": "delivered"}) self.assertEqual(sum(rma_lines.mapped("qty_to_receive")), 0) wizard = self.rma_make_picking.with_context( **{ "active_ids": rma_lines.ids, "active_model": "rma.order.line", "picking_type": "incoming", "active_id": 1, } ).create({}) with self.assertRaisesRegex(ValidationError, "No quantity to transfer"): wizard._create_picking() def test_08_supplier_rma_single_line(self): rma_line_id = self.rma_supplier_id.rma_line_ids[0].id wizard = self.rma_make_picking.with_context( active_ids=[rma_line_id], active_model="rma.order.line", picking_type="outgoing", active_id=2, ).create({}) wizard._create_picking() picking = self.rma_supplier_id.rma_line_ids[0]._get_out_pickings() partner = picking.partner_id 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_09_rma_state(self): rma = self.rma_customer_id self.assertEqual(rma.state, "approved") rma.rma_line_ids.action_rma_draft() self.assertEqual(rma.state, "draft") rma.action_rma_approve() self.assertEqual( rma.rma_line_ids.mapped("state"), ["approved", "approved", "approved"] ) def test_10_rma_cancel_line(self): # configure a new rule to make reception and expedition in 2 steps rma_route = self.env.ref("rma.route_rma_customer") rma_loc = self.env.ref("rma.location_rma") rma_loc2 = rma_loc.copy({"name": "rma loc shipping"}) rma_customer_rule = self.env.ref("rma.rule_rma_customer_out_pull") rma_customer_rule.write({"procure_method": "make_to_order", "sequence": 0}) self.env["stock.rule"].create( { "name": "reception => rma loc shipping", "action": "pull", "picking_type_id": self.wh.int_type_id.id, "location_src_id": self.wh.wh_input_stock_loc_id.id, "location_dest_id": rma_loc2.id, "procure_method": "make_to_stock", "route_id": rma_route.id, "warehouse_id": self.wh.id, "company_id": self.wh.company_id.id, } ) self.env["stock.rule"].create( { "name": "rma => reception", "action": "push", "picking_type_id": self.wh.int_type_id.id, "location_src_id": rma_loc.id, "location_dest_id": self.wh.wh_input_stock_loc_id.id, "procure_method": "make_to_stock", "route_id": rma_route.id, "warehouse_id": self.wh.id, "company_id": self.wh.company_id.id, } ) # Generate expedition for the rma group self.rma_customer_id.rma_line_ids.action_rma_to_approve() wizard = self.rma_make_picking.with_context( **{ "active_ids": self.rma_customer_id.rma_line_ids.ids, "active_model": "rma.order.line", "picking_type": "incoming", "active_id": 1, } ).create({}) wizard._create_picking() self.rma_customer_id.rma_line_ids.action_view_in_shipments() # cancel first line and check it cancel the dest moves, but leave the picking # ongoing for the 2 other lines first_rma_line = self.rma_customer_id.rma_line_ids[0] second_rma_line = self.rma_customer_id.rma_line_ids[1] first_line_in_move = first_rma_line.move_ids.filtered( lambda m: m.location_dest_id == rma_loc ) first_line_in_dest_move = first_line_in_move.move_dest_ids reception_picking = first_line_in_move.picking_id self.assertEqual(first_line_in_dest_move.state, "waiting") first_rma_line.action_rma_cancel() self.assertEqual(first_line_in_dest_move.state, "cancel") self.assertEqual(first_line_in_move.state, "cancel") self.assertEqual(reception_picking.state, "assigned") second_line_in_move = second_rma_line.move_ids.filtered( lambda m: m.location_dest_id == rma_loc ) self.assertEqual(second_line_in_move.state, "assigned") # generate 2 step expedition for the 2 remaining lines wizard = self.rma_make_picking.with_context( **{ "active_ids": self.rma_customer_id.rma_line_ids.filtered( lambda rol: rol.state != "canceled" ).ids, "active_model": "rma.order.line", "picking_type": "outgoing", "active_id": 1, } ).create({}) for line in wizard.item_ids: line.qty_to_deliver = line.product_qty wizard._create_picking() # cancel first line, check both chained move are canceled second_rma_out_move = second_rma_line.move_ids.filtered( lambda m: m.picking_id.picking_type_code == "outgoing" ) second_rma_out_move_orig = second_rma_out_move.move_orig_ids self.assertTrue(second_rma_out_move_orig) self.assertEqual(second_rma_out_move.state, "waiting") second_rma_line.action_rma_cancel() self.assertEqual(second_rma_out_move.state, "cancel") self.assertEqual(second_rma_out_move_orig.state, "cancel") # check picking is not canceled because third line has not been yet. self.assertEqual(second_rma_out_move.picking_id.state, "waiting")