mirror of
https://github.com/ForgeFlow/stock-rma.git
synced 2025-01-21 12:57:49 +02:00
[FIX] rma: rma_custmer_user has no write permissions in partner, so compute method fails.
[IMP] rma: use rma user in tests [FIX] rma_account: move_line_id field string [IMP] rma, rma_account, rma_sale, rma_purchase: tests for stock valuation [FIX] account_move_line_rma_order_line: minor lint, make auto-install [IMP] rma_account_unreconciled: use manager user in test
This commit is contained in:
committed by
Aaron ForgeFlow
parent
b7c0205607
commit
c65856d717
@@ -17,4 +17,5 @@
|
|||||||
"maintainers": ["ChisOForgeFlow"],
|
"maintainers": ["ChisOForgeFlow"],
|
||||||
"development_status": "Beta",
|
"development_status": "Beta",
|
||||||
"post_init_hook": "post_init_hook",
|
"post_init_hook": "post_init_hook",
|
||||||
|
"auto_install": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ class TestAccountMoveLineRmaOrderLine(common.SavepointCase):
|
|||||||
return user.id
|
return user.id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create_account_type(cls, name, atype, internal_group):
|
def _create_account_type(cls, name, account_type, internal_group):
|
||||||
acc_type = cls.acc_type_model.create(
|
acc_type = cls.acc_type_model.create(
|
||||||
{"name": name, "type": atype, "internal_group": internal_group}
|
{"name": name, "type": account_type, "internal_group": internal_group}
|
||||||
)
|
)
|
||||||
return acc_type
|
return acc_type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create_account(cls, acc_type, name, code, company):
|
def _create_account(cls, acc_type, name, code, company, reconcile=False):
|
||||||
"""Create an account."""
|
"""Create an account."""
|
||||||
account = cls.account_model.create(
|
account = cls.account_model.create(
|
||||||
{
|
{
|
||||||
@@ -97,6 +97,7 @@ class TestAccountMoveLineRmaOrderLine(common.SavepointCase):
|
|||||||
"code": code,
|
"code": code,
|
||||||
"user_type_id": acc_type.id,
|
"user_type_id": acc_type.id,
|
||||||
"company_id": company.id,
|
"company_id": company.id,
|
||||||
|
"reconcile": reconcile,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return account
|
return account
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2017 ForgeFlow
|
# Copyright 2017-22 ForgeFlow
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from odoo import fields, models
|
from odoo import fields, models
|
||||||
@@ -14,7 +14,10 @@ class ResPartner(models.Model):
|
|||||||
rma_line_ids = fields.One2many(
|
rma_line_ids = fields.One2many(
|
||||||
comodel_name="rma.order.line", string="RMAs", inverse_name="partner_id"
|
comodel_name="rma.order.line", string="RMAs", inverse_name="partner_id"
|
||||||
)
|
)
|
||||||
rma_line_count = fields.Integer(compute="_compute_rma_line_count")
|
rma_line_count = fields.Integer(
|
||||||
|
compute="_compute_rma_line_count",
|
||||||
|
compute_sudo=True,
|
||||||
|
)
|
||||||
|
|
||||||
def action_open_partner_rma(self):
|
def action_open_partner_rma(self):
|
||||||
action = self.env.ref("rma.action_rma_customer_lines")
|
action = self.env.ref("rma.action_rma_customer_lines")
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ class StockRule(models.Model):
|
|||||||
res["partner_id"] = line.delivery_address_id.id
|
res["partner_id"] = line.delivery_address_id.id
|
||||||
else:
|
else:
|
||||||
res["partner_id"] = line.rma_id.partner_id.id
|
res["partner_id"] = line.rma_id.partner_id.id
|
||||||
|
# We are not checking the reference move here because if stock account
|
||||||
|
# is not installed, there is no way to know the cost of the stock move
|
||||||
|
# so better use the standard cost in this case.
|
||||||
company_id = res["company_id"]
|
company_id = res["company_id"]
|
||||||
company = self.env["res.company"].browse(company_id)
|
company = self.env["res.company"].browse(company_id)
|
||||||
cost = product_id.with_company(company).standard_price
|
cost = product_id.with_company(company).standard_price
|
||||||
|
|||||||
@@ -11,15 +11,18 @@ class TestRma(common.SavepointCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestRma, cls).setUpClass()
|
super(TestRma, cls).setUpClass()
|
||||||
|
# models
|
||||||
cls.rma_make_picking = cls.env["rma_make_picking.wizard"]
|
cls.rma_make_picking = cls.env["rma_make_picking.wizard"]
|
||||||
cls.make_supplier_rma = cls.env["rma.order.line.make.supplier.rma"]
|
cls.make_supplier_rma = cls.env["rma.order.line.make.supplier.rma"]
|
||||||
cls.rma_add_stock_move = cls.env["rma_add_stock_move"]
|
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.stockpicking = cls.env["stock.picking"]
|
||||||
cls.rma = cls.env["rma.order"]
|
cls.rma = cls.env["rma.order"]
|
||||||
cls.rma_line = cls.env["rma.order.line"]
|
cls.rma_line = cls.env["rma.order.line"]
|
||||||
cls.rma_op = cls.env["rma.operation"]
|
cls.rma_op = cls.env["rma.operation"]
|
||||||
cls.product_product_model = cls.env["product.product"]
|
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_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_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.rma_ds_replace_op_id = cls.env.ref("rma.rma_operation_ds_replace")
|
||||||
@@ -31,16 +34,34 @@ class TestRma(common.SavepointCase):
|
|||||||
cls.product_2 = cls._create_product("PT2")
|
cls.product_2 = cls._create_product("PT2")
|
||||||
cls.product_3 = cls._create_product("PT3")
|
cls.product_3 = cls._create_product("PT3")
|
||||||
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
|
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
|
||||||
cls.env.user.company_id.group_rma_delivery_address = True
|
cls.company = cls.env.company
|
||||||
cls.env.user.company_id.group_rma_lines = True
|
cls.company.group_rma_delivery_address = True
|
||||||
|
cls.company.group_rma_lines = True
|
||||||
|
|
||||||
cls.partner_id = cls.env.ref("base.res_partner_2")
|
cls.partner_id = cls.env.ref("base.res_partner_2")
|
||||||
cls.stock_location = cls.env.ref("stock.stock_location_stock")
|
cls.stock_location = cls.env.ref("stock.stock_location_stock")
|
||||||
wh = cls.env.ref("stock.warehouse0")
|
cls.wh = cls.env.ref("stock.warehouse0")
|
||||||
cls.stock_rma_location = wh.lot_rma_id
|
cls.stock_rma_location = cls.wh.lot_rma_id
|
||||||
cls.customer_location = cls.env.ref("stock.stock_location_customers")
|
cls.customer_location = cls.env.ref("stock.stock_location_customers")
|
||||||
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
|
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
|
||||||
cls.product_uom_id = cls.env.ref("uom.product_uom_unit")
|
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_manager = cls.env.ref("rma.group_rma_manager")
|
||||||
|
cls.g_rma_supplier_user = cls.env.ref("rma.group_rma_supplier_user")
|
||||||
|
cls.g_account_manager = cls.env.ref("account.group_account_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.g_account_manager],
|
||||||
|
cls.company,
|
||||||
|
)
|
||||||
# Customer RMA:
|
# Customer RMA:
|
||||||
products2move = [(cls.product_1, 3), (cls.product_2, 5), (cls.product_3, 2)]
|
products2move = [(cls.product_1, 3), (cls.product_2, 5), (cls.product_3, 2)]
|
||||||
cls.rma_customer_id = cls._create_rma_from_move(
|
cls.rma_customer_id = cls._create_rma_from_move(
|
||||||
@@ -59,11 +80,64 @@ class TestRma(common.SavepointCase):
|
|||||||
products2move, "supplier", cls.env.ref("base.res_partner_2"), dropship=False
|
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_lines:
|
||||||
|
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_lines:
|
||||||
|
mv.quantity_done = mv.product_uom_qty
|
||||||
|
picking._action_done()
|
||||||
|
return picking
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create_product_category(
|
def _create_product_category(
|
||||||
cls, rma_approval_policy, rma_customer_operation_id, rma_supplier_operation_id
|
cls, rma_approval_policy, rma_customer_operation_id, rma_supplier_operation_id
|
||||||
):
|
):
|
||||||
return cls.env["product.category"].create(
|
return cls.product_ctg_model.create(
|
||||||
{
|
{
|
||||||
"name": "Test category",
|
"name": "Test category",
|
||||||
"rma_approval_policy": rma_approval_policy,
|
"rma_approval_policy": rma_approval_policy,
|
||||||
@@ -79,45 +153,124 @@ class TestRma(common.SavepointCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create_picking(cls, partner):
|
def _create_picking(cls, partner, picking_type):
|
||||||
return cls.stockpicking.create(
|
return cls.stockpicking.create(
|
||||||
{
|
{
|
||||||
"partner_id": partner.id,
|
"partner_id": partner.id,
|
||||||
"picking_type_id": cls.env.ref("stock.picking_type_in").id,
|
"picking_type_id": picking_type.id,
|
||||||
"location_id": cls.stock_location.id,
|
"location_id": cls.stock_location.id,
|
||||||
"location_dest_id": cls.supplier_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.onchange_picking_type()
|
||||||
|
picking.action_confirm()
|
||||||
|
picking.action_assign()
|
||||||
|
for ml in picking.move_lines:
|
||||||
|
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.inventory"].create(
|
||||||
|
{
|
||||||
|
"name": "Initial inventory",
|
||||||
|
"line_ids": [
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"product_id": product.id,
|
||||||
|
"product_uom_id": product.uom_id.id,
|
||||||
|
"product_qty": qty,
|
||||||
|
"location_id": location.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
inventory._action_start()
|
||||||
|
inventory.action_validate()
|
||||||
|
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
|
@classmethod
|
||||||
def _create_rma_from_move(
|
def _create_rma_from_move(
|
||||||
cls, products2move, r_type, partner, dropship, supplier_address_id=None
|
cls, products2move, r_type, partner, dropship, supplier_address_id=None
|
||||||
):
|
):
|
||||||
picking_in = cls._create_picking(partner)
|
|
||||||
|
|
||||||
moves = []
|
moves = []
|
||||||
if r_type == "customer":
|
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:
|
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(
|
move_values = cls._prepare_move(
|
||||||
item[0],
|
product,
|
||||||
item[1],
|
product_qty,
|
||||||
cls.stock_location,
|
cls.stock_location,
|
||||||
cls.customer_location,
|
cls.customer_location,
|
||||||
picking_in,
|
picking,
|
||||||
)
|
)
|
||||||
moves.append(cls.env["stock.move"].create(move_values))
|
moves.append(cls.env["stock.move"].create(move_values))
|
||||||
else:
|
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:
|
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(
|
move_values = cls._prepare_move(
|
||||||
item[0],
|
product,
|
||||||
item[1],
|
product_qty,
|
||||||
cls.supplier_location,
|
cls.supplier_location,
|
||||||
cls.stock_rma_location,
|
cls.stock_rma_location,
|
||||||
picking_in,
|
picking,
|
||||||
)
|
)
|
||||||
moves.append(cls.env["stock.move"].create(move_values))
|
moves.append(cls.env["stock.move"].create(move_values))
|
||||||
|
# Process the picking
|
||||||
|
cls._do_picking(picking)
|
||||||
# Create the RMA from the stock_move
|
# Create the RMA from the stock_move
|
||||||
rma_id = cls.rma.create(
|
rma_id = cls.rma.with_user(cls.rma_basic_user).create(
|
||||||
{
|
{
|
||||||
"reference": "0001",
|
"reference": "0001",
|
||||||
"type": r_type,
|
"type": r_type,
|
||||||
@@ -127,7 +280,7 @@ class TestRma(common.SavepointCase):
|
|||||||
)
|
)
|
||||||
for move in moves:
|
for move in moves:
|
||||||
if r_type == "customer":
|
if r_type == "customer":
|
||||||
wizard = cls.rma_add_stock_move.new(
|
wizard = cls.rma_add_stock_move.with_user(cls.rma_basic_user).new(
|
||||||
{
|
{
|
||||||
"move_ids": [(4, move.id)],
|
"move_ids": [(4, move.id)],
|
||||||
"rma_id": rma_id.id,
|
"rma_id": rma_id.id,
|
||||||
@@ -144,12 +297,14 @@ class TestRma(common.SavepointCase):
|
|||||||
"active_model": "rma.order",
|
"active_model": "rma.order",
|
||||||
}
|
}
|
||||||
).default_get([str(move.id), str(cls.partner_id.id)])
|
).default_get([str(move.id), str(cls.partner_id.id)])
|
||||||
data = wizard.with_context(
|
data = (
|
||||||
customer=1
|
wizard.with_user(cls.rma_basic_user)
|
||||||
)._prepare_rma_line_from_stock_move(move)
|
.with_context(customer=1)
|
||||||
|
._prepare_rma_line_from_stock_move(move)
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
wizard = cls.rma_add_stock_move.new(
|
wizard = cls.rma_add_stock_move.with_user(cls.rma_basic_user).new(
|
||||||
{
|
{
|
||||||
"move_ids": [(4, move.id)],
|
"move_ids": [(4, move.id)],
|
||||||
"rma_id": rma_id.id,
|
"rma_id": rma_id.id,
|
||||||
@@ -165,7 +320,9 @@ class TestRma(common.SavepointCase):
|
|||||||
"active_model": "rma.order",
|
"active_model": "rma.order",
|
||||||
}
|
}
|
||||||
).default_get([str(move.id), str(cls.partner_id.id)])
|
).default_get([str(move.id), str(cls.partner_id.id)])
|
||||||
data = wizard._prepare_rma_line_from_stock_move(move)
|
data = wizard.with_user(
|
||||||
|
cls.rma_basic_user
|
||||||
|
)._prepare_rma_line_from_stock_move(move)
|
||||||
data["type"] = "supplier"
|
data["type"] = "supplier"
|
||||||
if dropship:
|
if dropship:
|
||||||
data.update(
|
data.update(
|
||||||
@@ -173,21 +330,15 @@ class TestRma(common.SavepointCase):
|
|||||||
operation_id=cls.rma_ds_replace_op_id.id,
|
operation_id=cls.rma_ds_replace_op_id.id,
|
||||||
supplier_address_id=supplier_address_id.id,
|
supplier_address_id=supplier_address_id.id,
|
||||||
)
|
)
|
||||||
cls.line = cls.rma_line.create(data)
|
cls.line = cls.rma_line.with_user(cls.rma_basic_user).create(data)
|
||||||
cls.line._onchange_product_id()
|
cls.line._onchange_product_id()
|
||||||
cls.line._onchange_operation_id()
|
cls.line._onchange_operation_id()
|
||||||
cls.line.action_rma_to_approve()
|
cls.line.action_rma_to_approve()
|
||||||
rma_id._get_default_type()
|
rma_id._get_default_type()
|
||||||
rma_id._compute_in_shipment_count()
|
|
||||||
rma_id._compute_out_shipment_count()
|
|
||||||
rma_id._compute_supplier_line_count()
|
|
||||||
rma_id._compute_line_count()
|
|
||||||
rma_id.action_view_in_shipments()
|
rma_id.action_view_in_shipments()
|
||||||
rma_id.action_view_out_shipments()
|
rma_id.action_view_out_shipments()
|
||||||
rma_id.action_view_lines()
|
rma_id.action_view_lines()
|
||||||
|
|
||||||
rma_id.partner_id.action_open_partner_rma()
|
rma_id.partner_id.action_open_partner_rma()
|
||||||
rma_id.partner_id._compute_rma_line_count()
|
|
||||||
return rma_id
|
return rma_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -205,23 +356,8 @@ class TestRma(common.SavepointCase):
|
|||||||
"product_uom_qty": qty,
|
"product_uom_qty": qty,
|
||||||
"location_id": location_id,
|
"location_id": location_id,
|
||||||
"location_dest_id": dest.id,
|
"location_dest_id": dest.id,
|
||||||
"move_line_ids": [
|
|
||||||
(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
{
|
|
||||||
"product_id": product.id,
|
|
||||||
"product_uom_id": product.uom_id.id,
|
|
||||||
"qty_done": qty,
|
|
||||||
"location_id": location_id,
|
|
||||||
"location_dest_id": dest.id,
|
|
||||||
"package_id": False,
|
|
||||||
"owner_id": False,
|
|
||||||
"lot_id": False,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
"picking_id": picking_in.id,
|
"picking_id": picking_in.id,
|
||||||
|
"price_unit": product.standard_price,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _check_equal_quantity(self, qty1, qty2, msg):
|
def _check_equal_quantity(self, qty1, qty2, msg):
|
||||||
@@ -511,8 +647,12 @@ class TestRma(common.SavepointCase):
|
|||||||
2,
|
2,
|
||||||
"Wrong qty_delivered",
|
"Wrong qty_delivered",
|
||||||
)
|
)
|
||||||
self.line.action_rma_done()
|
self.rma_customer_id.rma_line_ids.action_rma_done()
|
||||||
self.assertEqual(self.line.state, "done", "Wrong State")
|
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_in_shipments()
|
||||||
self.rma_customer_id.action_view_out_shipments()
|
self.rma_customer_id.action_view_out_shipments()
|
||||||
self.rma_customer_id.action_view_lines()
|
self.rma_customer_id.action_view_lines()
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class RmaOrderLine(models.Model):
|
|||||||
move_line_ids = fields.One2many(
|
move_line_ids = fields.One2many(
|
||||||
comodel_name="account.move.line",
|
comodel_name="account.move.line",
|
||||||
inverse_name="rma_line_id",
|
inverse_name="rma_line_id",
|
||||||
string="Refund Lines",
|
string="Journal Items",
|
||||||
copy=False,
|
copy=False,
|
||||||
index=True,
|
index=True,
|
||||||
readonly=True,
|
readonly=True,
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
from . import test_rma_account
|
from . import test_rma_account
|
||||||
|
from . import test_rma_stock_account
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2017-18 ForgeFlow S.L.
|
# Copyright 2017-22 ForgeFlow S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
from odoo import fields
|
from odoo import fields
|
||||||
|
|||||||
143
rma_account/tests/test_rma_stock_account.py
Normal file
143
rma_account/tests/test_rma_stock_account.py
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# Copyright 2017-22 ForgeFlow S.L.
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
|
from odoo.tests.common import Form
|
||||||
|
|
||||||
|
# pylint: disable=odoo-addons-relative-import
|
||||||
|
from odoo.addons.rma.tests.test_rma import TestRma
|
||||||
|
|
||||||
|
|
||||||
|
class TestRmaStockAccount(TestRma):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestRmaStockAccount, cls).setUpClass()
|
||||||
|
cls.acc_type_model = cls.env["account.account.type"]
|
||||||
|
cls.account_model = cls.env["account.account"]
|
||||||
|
cls.g_account_user = cls.env.ref("account.group_account_user")
|
||||||
|
# we create new products to ensure previous layers do not affect when
|
||||||
|
# running FIFO
|
||||||
|
cls.product_fifo_1 = cls._create_product("product_fifo1")
|
||||||
|
cls.product_fifo_2 = cls._create_product("product_fifo2")
|
||||||
|
cls.product_fifo_3 = cls._create_product("product_fifo3")
|
||||||
|
cls.rma_basic_user.write({"groups_id": [(4, cls.g_account_user.id)]})
|
||||||
|
# The product category created in the base module is not automated valuation
|
||||||
|
# we have to create a new category here
|
||||||
|
# Create account for Goods Received Not Invoiced
|
||||||
|
acc_type = cls._create_account_type("equity", "other")
|
||||||
|
name = "Goods Received Not Invoiced"
|
||||||
|
code = "grni"
|
||||||
|
cls.account_grni = cls._create_account(acc_type, name, code, cls.company, True)
|
||||||
|
# Create account for Cost of Goods Sold
|
||||||
|
acc_type = cls._create_account_type("expense", "other")
|
||||||
|
name = "Cost of Goods Sold"
|
||||||
|
code = "cogs"
|
||||||
|
cls.account_cogs = cls._create_account(acc_type, name, code, cls.company, False)
|
||||||
|
# Create account for Inventory
|
||||||
|
acc_type = cls._create_account_type("asset", "other")
|
||||||
|
name = "Inventory"
|
||||||
|
code = "inventory"
|
||||||
|
cls.account_inventory = cls._create_account(
|
||||||
|
acc_type, name, code, cls.company, False
|
||||||
|
)
|
||||||
|
product_ctg = cls.product_ctg_model.create(
|
||||||
|
{
|
||||||
|
"name": "test_product_ctg",
|
||||||
|
"property_stock_valuation_account_id": cls.account_inventory.id,
|
||||||
|
"property_valuation": "real_time",
|
||||||
|
"property_stock_account_input_categ_id": cls.account_grni.id,
|
||||||
|
"property_stock_account_output_categ_id": cls.account_cogs.id,
|
||||||
|
"rma_approval_policy": "one_step",
|
||||||
|
"rma_customer_operation_id": cls.rma_cust_replace_op_id.id,
|
||||||
|
"rma_supplier_operation_id": cls.rma_sup_replace_op_id.id,
|
||||||
|
"property_cost_method": "fifo",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# We use FIFO to test the cost is taken from the original layers
|
||||||
|
cls.product_fifo_1.categ_id = product_ctg
|
||||||
|
cls.product_fifo_2.categ_id = product_ctg
|
||||||
|
cls.product_fifo_3.categ_id = product_ctg
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _create_account_type(cls, name, a_type):
|
||||||
|
acc_type = cls.acc_type_model.create(
|
||||||
|
{"name": name, "type": a_type, "internal_group": name}
|
||||||
|
)
|
||||||
|
return acc_type
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _create_account(cls, acc_type, name, code, company, reconcile):
|
||||||
|
"""Create an account."""
|
||||||
|
account = cls.account_model.create(
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"code": code,
|
||||||
|
"user_type_id": acc_type.id,
|
||||||
|
"company_id": company.id,
|
||||||
|
"reconcile": reconcile,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return account
|
||||||
|
|
||||||
|
def check_accounts_used(
|
||||||
|
self, account_move, debit_account=False, credit_account=False
|
||||||
|
):
|
||||||
|
debit_line = account_move.mapped("line_ids").filtered(lambda l: l.debit)
|
||||||
|
credit_line = account_move.mapped("line_ids").filtered(lambda l: l.credit)
|
||||||
|
if debit_account:
|
||||||
|
self.assertEqual(debit_line.account_id.code, debit_account)
|
||||||
|
if credit_account:
|
||||||
|
self.assertEqual(credit_line.account_id.code, credit_account)
|
||||||
|
|
||||||
|
def test_01_cost_from_standard(self):
|
||||||
|
"""
|
||||||
|
Test the price unit is taken from the standard cost when there is no reference
|
||||||
|
"""
|
||||||
|
self.product_fifo_1.standard_price = 15
|
||||||
|
rma_line = Form(self.rma_line.with_user(self.rma_basic_user))
|
||||||
|
rma_line.partner_id = self.partner_id
|
||||||
|
rma_line.product_id = self.product_fifo_1
|
||||||
|
rma_line.price_unit = 1234
|
||||||
|
rma_line = rma_line.save()
|
||||||
|
rma_line.action_rma_to_approve()
|
||||||
|
picking = self._receive_rma(rma_line)
|
||||||
|
self.assertEqual(picking.move_lines.stock_valuation_layer_ids.value, 15.0)
|
||||||
|
account_move = picking.move_lines.stock_valuation_layer_ids.account_move_id
|
||||||
|
self.check_accounts_used(
|
||||||
|
account_move, debit_account="inventory", credit_account="cogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_02_cost_from_move(self):
|
||||||
|
"""
|
||||||
|
Test the price unit is taken from the cost of the stock move when the
|
||||||
|
reference is the stock move
|
||||||
|
"""
|
||||||
|
# Set a standard price on the products
|
||||||
|
self.product_fifo_1.standard_price = 10
|
||||||
|
self.product_fifo_2.standard_price = 20
|
||||||
|
self.product_fifo_3.standard_price = 30
|
||||||
|
self._create_inventory(
|
||||||
|
self.product_fifo_1, 20.0, self.env.ref("stock.stock_location_customers")
|
||||||
|
)
|
||||||
|
products2move = [
|
||||||
|
(self.product_fifo_1, 3),
|
||||||
|
(self.product_fifo_2, 5),
|
||||||
|
(self.product_fifo_3, 2),
|
||||||
|
]
|
||||||
|
rma_customer_id = self._create_rma_from_move(
|
||||||
|
products2move,
|
||||||
|
"customer",
|
||||||
|
self.env.ref("base.res_partner_2"),
|
||||||
|
dropship=False,
|
||||||
|
)
|
||||||
|
# Set an incorrect price in the RMA (this should not affect cost)
|
||||||
|
rma_customer_id.rma_line_ids.price_unit = 999
|
||||||
|
rma_customer_id.rma_line_ids.action_rma_to_approve()
|
||||||
|
picking = self._receive_rma(rma_customer_id.rma_line_ids)
|
||||||
|
# Test the value in the layers of the incoming stock move is used
|
||||||
|
for rma_line in rma_customer_id.rma_line_ids:
|
||||||
|
value_origin = rma_line.reference_move_id.stock_valuation_layer_ids.value
|
||||||
|
move_product = picking.move_lines.filtered(
|
||||||
|
lambda l: l.product_id == rma_line.product_id
|
||||||
|
)
|
||||||
|
value_used = move_product.stock_valuation_layer_ids.value
|
||||||
|
self.assertEqual(value_used, -value_origin)
|
||||||
@@ -10,7 +10,9 @@ class TestRmaAccountUnreconciled(TestRma):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.rma_refund_wiz = cls.env["rma.refund"]
|
cls.rma_refund_wiz = cls.env["rma.refund"]
|
||||||
for categ in cls.rma_customer_id.mapped("rma_line_ids.product_id.categ_id"):
|
for categ in cls.rma_customer_id.with_user(cls.rma_manager_user).mapped(
|
||||||
|
"rma_line_ids.product_id.categ_id"
|
||||||
|
):
|
||||||
categ.write(
|
categ.write(
|
||||||
{
|
{
|
||||||
"property_valuation": "real_time",
|
"property_valuation": "real_time",
|
||||||
@@ -27,7 +29,9 @@ class TestRmaAccountUnreconciled(TestRma):
|
|||||||
"reconcile": True,
|
"reconcile": True,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for product in cls.rma_customer_id.mapped("rma_line_ids.product_id"):
|
for product in cls.rma_customer_id.with_user(cls.rma_manager_user).mapped(
|
||||||
|
"rma_line_ids.product_id"
|
||||||
|
):
|
||||||
product.write(
|
product.write(
|
||||||
{
|
{
|
||||||
"standard_price": 10.0,
|
"standard_price": 10.0,
|
||||||
@@ -80,7 +84,9 @@ class TestRmaAccountUnreconciled(TestRma):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
make_refund.invoice_refund()
|
make_refund.invoice_refund()
|
||||||
self.rma_customer_id.rma_line_ids.refund_line_ids.move_id.filtered(
|
self.rma_customer_id.with_user(
|
||||||
|
self.rma_manager_user
|
||||||
|
).rma_line_ids.refund_line_ids.move_id.filtered(
|
||||||
lambda x: x.state != "posted"
|
lambda x: x.state != "posted"
|
||||||
).action_post()
|
).action_post()
|
||||||
for rma_line in self.rma_customer_id.rma_line_ids:
|
for rma_line in self.rma_customer_id.rma_line_ids:
|
||||||
@@ -98,7 +104,7 @@ class TestRmaAccountUnreconciled(TestRma):
|
|||||||
3,
|
3,
|
||||||
)
|
)
|
||||||
for rma_line in self.rma_customer_id.rma_line_ids:
|
for rma_line in self.rma_customer_id.rma_line_ids:
|
||||||
aml_domain = rma_line.action_view_unreconciled().get("domain")
|
aml_domain = rma_line.sudo().action_view_unreconciled().get("domain")
|
||||||
aml_lines = (
|
aml_lines = (
|
||||||
aml_domain and self.env["account.move.line"].search(aml_domain) or False
|
aml_domain and self.env["account.move.line"].search(aml_domain) or False
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class StockRule(models.Model):
|
|||||||
if moves:
|
if moves:
|
||||||
# TODO: Should we be smart in the choice of the move?
|
# TODO: Should we be smart in the choice of the move?
|
||||||
layers = moves.mapped("stock_valuation_layer_ids")
|
layers = moves.mapped("stock_valuation_layer_ids")
|
||||||
|
if layers:
|
||||||
cost = layers[-1].unit_cost
|
cost = layers[-1].unit_cost
|
||||||
res["price_unit"] = cost
|
res["price_unit"] = cost
|
||||||
elif line.account_move_line_id.purchase_line_id:
|
elif line.account_move_line_id.purchase_line_id:
|
||||||
@@ -44,6 +45,7 @@ class StockRule(models.Model):
|
|||||||
moves = purchase_lines.mapped("move_ids")
|
moves = purchase_lines.mapped("move_ids")
|
||||||
if moves:
|
if moves:
|
||||||
layers = moves.mapped("stock_valuation_layer_ids")
|
layers = moves.mapped("stock_valuation_layer_ids")
|
||||||
|
if layers:
|
||||||
cost = layers[-1].unit_cost
|
cost = layers[-1].unit_cost
|
||||||
# TODO: Should we be smart in the choice of the move?
|
# TODO: Should we be smart in the choice of the move?
|
||||||
res["price_unit"] = cost
|
res["price_unit"] = cost
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
from . import test_rma_purchase
|
from . import test_rma_purchase
|
||||||
|
from . import test_rma_stock_account_purchase
|
||||||
|
|||||||
81
rma_purchase/tests/test_rma_stock_account_purchase.py
Normal file
81
rma_purchase/tests/test_rma_stock_account_purchase.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Copyright 2017-22 ForgeFlow S.L.
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
|
from odoo.fields import Datetime
|
||||||
|
from odoo.tests.common import Form
|
||||||
|
|
||||||
|
# pylint: disable=odoo-addons-relative-import
|
||||||
|
from odoo.addons.rma_account.tests.test_rma_stock_account import TestRmaStockAccount
|
||||||
|
|
||||||
|
|
||||||
|
class TestRmaStockAccountPurchase(TestRmaStockAccount):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestRmaStockAccountPurchase, cls).setUpClass()
|
||||||
|
cls.pol_model = cls.env["purchase.order.line"]
|
||||||
|
cls.po_model = cls.env["purchase.order"]
|
||||||
|
# Create PO:
|
||||||
|
cls.product_fifo_1.standard_price = 1234
|
||||||
|
cls.po = cls.po_model.create(
|
||||||
|
{
|
||||||
|
"partner_id": cls.partner_id.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.pol_1 = cls.pol_model.create(
|
||||||
|
{
|
||||||
|
"name": cls.product_fifo_1.name,
|
||||||
|
"order_id": cls.po.id,
|
||||||
|
"product_id": cls.product_fifo_1.id,
|
||||||
|
"product_qty": 20.0,
|
||||||
|
"product_uom": cls.product_fifo_1.uom_id.id,
|
||||||
|
"price_unit": 100.0,
|
||||||
|
"date_planned": Datetime.now(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.po.button_confirm()
|
||||||
|
cls._do_picking(cls.po.picking_ids)
|
||||||
|
|
||||||
|
def test_01_cost_from_po_move(self):
|
||||||
|
"""
|
||||||
|
Test the price unit is taken from the cost of the stock move associated to
|
||||||
|
the PO
|
||||||
|
"""
|
||||||
|
self.product_fifo_1.standard_price = 1234 # this should not be taken
|
||||||
|
supplier_view = self.env.ref("rma_purchase.view_rma_line_form")
|
||||||
|
rma_line = Form(
|
||||||
|
self.rma_line.with_context(supplier=1).with_user(self.rma_basic_user),
|
||||||
|
view=supplier_view.id,
|
||||||
|
)
|
||||||
|
rma_line.partner_id = self.po.partner_id
|
||||||
|
rma_line.purchase_order_line_id = self.pol_1
|
||||||
|
rma_line.price_unit = 4356
|
||||||
|
rma_line = rma_line.save()
|
||||||
|
rma_line.action_rma_to_approve()
|
||||||
|
picking = self._deliver_rma(rma_line)
|
||||||
|
# The price is not the standard price, is the value of the incoming layer
|
||||||
|
# of the PO
|
||||||
|
rma_move_value = picking.move_lines.stock_valuation_layer_ids.value
|
||||||
|
po_move_value = self.po.picking_ids.mapped(
|
||||||
|
"move_lines.stock_valuation_layer_ids"
|
||||||
|
)[-1].value
|
||||||
|
self.assertEqual(-rma_move_value, po_move_value)
|
||||||
|
# Test the accounts used
|
||||||
|
account_move = picking.move_lines.stock_valuation_layer_ids.account_move_id
|
||||||
|
self.check_accounts_used(account_move, "grni", "inventory")
|
||||||
|
# Now forcing a refund to check the stock journals
|
||||||
|
rma_line.refund_policy = "ordered"
|
||||||
|
make_refund = (
|
||||||
|
self.env["rma.refund"]
|
||||||
|
.with_context(
|
||||||
|
{
|
||||||
|
"customer": True,
|
||||||
|
"active_ids": rma_line.ids,
|
||||||
|
"active_model": "rma.order.line",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.create({"description": "Test refund"})
|
||||||
|
)
|
||||||
|
make_refund.invoice_refund()
|
||||||
|
rma_line.refund_line_ids.move_id.action_post()
|
||||||
|
account_move = rma_line.mapped("refund_line_ids.move_id")
|
||||||
|
self.check_accounts_used(account_move, credit_account="grni")
|
||||||
@@ -37,6 +37,7 @@ class StockRule(models.Model):
|
|||||||
if moves:
|
if moves:
|
||||||
# TODO: Should we be smart in the choice of the move?
|
# TODO: Should we be smart in the choice of the move?
|
||||||
layers = moves.mapped("stock_valuation_layer_ids")
|
layers = moves.mapped("stock_valuation_layer_ids")
|
||||||
|
if layers:
|
||||||
cost = layers[-1].unit_cost
|
cost = layers[-1].unit_cost
|
||||||
res["price_unit"] = cost
|
res["price_unit"] = cost
|
||||||
elif line.account_move_line_id:
|
elif line.account_move_line_id:
|
||||||
@@ -44,6 +45,7 @@ class StockRule(models.Model):
|
|||||||
moves = sale_lines.mapped("move_ids")
|
moves = sale_lines.mapped("move_ids")
|
||||||
if moves:
|
if moves:
|
||||||
layers = moves.mapped("stock_valuation_layer_ids")
|
layers = moves.mapped("stock_valuation_layer_ids")
|
||||||
|
if layers:
|
||||||
cost = layers[-1].unit_cost
|
cost = layers[-1].unit_cost
|
||||||
# TODO: Should we be smart in the choice of the move?
|
# TODO: Should we be smart in the choice of the move?
|
||||||
res["price_unit"] = cost
|
res["price_unit"] = cost
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
# Copyright 2020 ForgeFlow S.L.
|
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
|
||||||
|
|
||||||
from . import test_rma_sale
|
from . import test_rma_sale
|
||||||
|
from . import test_rma_stock_account_sale
|
||||||
|
|||||||
74
rma_sale/tests/test_rma_stock_account_sale.py
Normal file
74
rma_sale/tests/test_rma_stock_account_sale.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Copyright 2022 ForgeFlow S.L.
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||||
|
|
||||||
|
from odoo.tests.common import Form
|
||||||
|
|
||||||
|
# pylint: disable=odoo-addons-relative-import
|
||||||
|
from odoo.addons.rma_account.tests.test_rma_stock_account import TestRmaStockAccount
|
||||||
|
|
||||||
|
|
||||||
|
class TestRmaStockAccountSale(TestRmaStockAccount):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestRmaStockAccountSale, cls).setUpClass()
|
||||||
|
customer1 = cls.env["res.partner"].create({"name": "Customer 1"})
|
||||||
|
cls.product_fifo_1.standard_price = 1234
|
||||||
|
cls._create_inventory(cls.product_fifo_1, 20.0, cls.env.ref("rma.location_rma"))
|
||||||
|
cls.so1 = cls.env["sale.order"].create(
|
||||||
|
{
|
||||||
|
"partner_id": customer1.id,
|
||||||
|
"partner_invoice_id": customer1.id,
|
||||||
|
"partner_shipping_id": customer1.id,
|
||||||
|
"order_line": [
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": cls.product_fifo_1.name,
|
||||||
|
"product_id": cls.product_fifo_1.id,
|
||||||
|
"product_uom_qty": 20.0,
|
||||||
|
"product_uom": cls.product_fifo_1.uom_id.id,
|
||||||
|
"price_unit": 800,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
"pricelist_id": cls.env.ref("product.list0").id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.so1.action_confirm()
|
||||||
|
for ml in cls.so1.picking_ids.move_line_ids:
|
||||||
|
ml.qty_done = ml.product_uom_qty
|
||||||
|
cls.so1.picking_ids.button_validate()
|
||||||
|
|
||||||
|
def test_01_cost_from_so_move(self):
|
||||||
|
"""
|
||||||
|
Test the price unit is taken from the cost of the stock move associated to
|
||||||
|
the SO
|
||||||
|
"""
|
||||||
|
so_line = self.so1.order_line.filtered(
|
||||||
|
lambda r: r.product_id == self.product_fifo_1
|
||||||
|
)
|
||||||
|
self.product_fifo_1.standard_price = 5678 # this should not be taken
|
||||||
|
customer_view = self.env.ref("rma_sale.view_rma_line_form")
|
||||||
|
rma_line = Form(
|
||||||
|
self.rma_line.with_context(customer=1).with_user(self.rma_basic_user),
|
||||||
|
view=customer_view.id,
|
||||||
|
)
|
||||||
|
rma_line.partner_id = self.so1.partner_id
|
||||||
|
rma_line.sale_line_id = so_line
|
||||||
|
rma_line.price_unit = 4356
|
||||||
|
rma_line = rma_line.save()
|
||||||
|
rma_line.action_rma_to_approve()
|
||||||
|
picking = self._receive_rma(rma_line)
|
||||||
|
# The price is not the standard price, is the value of the outgoing layer
|
||||||
|
# of the SO
|
||||||
|
rma_move_value = picking.move_lines.stock_valuation_layer_ids.value
|
||||||
|
so_move_value = self.so1.picking_ids.mapped(
|
||||||
|
"move_lines.stock_valuation_layer_ids"
|
||||||
|
)[-1].value
|
||||||
|
self.assertEqual(rma_move_value, -so_move_value)
|
||||||
|
# Test the accounts used
|
||||||
|
account_move = picking.move_lines.stock_valuation_layer_ids.account_move_id
|
||||||
|
self.check_accounts_used(
|
||||||
|
account_move, debit_account="inventory", credit_account="cogs"
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user