mirror of
https://github.com/bringout/oca-workflow-process.git
synced 2026-04-19 07:52:06 +02:00
Initial commit: OCA Workflow Process packages (456 packages)
This commit is contained in:
commit
d366e42934
18799 changed files with 1284507 additions and 0 deletions
|
|
@ -0,0 +1,6 @@
|
|||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from . import test_purchase_request_allocation
|
||||
from . import test_purchase_request_procurement
|
||||
from . import test_purchase_request_to_rfq
|
||||
from . import test_purchase_request
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
# Copyright 2018-2019 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import SUPERUSER_ID, exceptions
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests.common import Form, TransactionCase
|
||||
|
||||
|
||||
class TestPurchaseRequest(TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPurchaseRequest, self).setUp()
|
||||
self.purchase_request_obj = self.env["purchase.request"]
|
||||
self.purchase_request_line_obj = self.env["purchase.request.line"]
|
||||
self.purchase_order = self.env["purchase.order"]
|
||||
self.wiz = self.env["purchase.request.line.make.purchase.order"]
|
||||
self.picking_type_id = self.env.ref("stock.picking_type_in")
|
||||
vals = {
|
||||
"group_id": self.env["procurement.group"].create({}).id,
|
||||
"picking_type_id": self.picking_type_id.id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
self.purchase_request = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": self.purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_13").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
}
|
||||
self.purchase_request_line_obj.create(vals)
|
||||
|
||||
def test_purchase_request_line_action(self):
|
||||
action = self.purchase_request.line_ids.action_show_details()
|
||||
self.assertEqual(action["res_id"], self.purchase_request.line_ids.id)
|
||||
|
||||
def test_purchase_request_status(self):
|
||||
"""Tests Purchase Request status workflow."""
|
||||
purchase_request = self.purchase_request
|
||||
purchase_request.write({"assigned_to": SUPERUSER_ID})
|
||||
self.assertEqual(purchase_request.is_editable, True, "Should be editable")
|
||||
self.assertEqual(purchase_request.state, "draft", "Should be in state draft")
|
||||
purchase_request.button_to_approve()
|
||||
self.assertEqual(
|
||||
purchase_request.state, "to_approve", "Should be in state to_approve"
|
||||
)
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
purchase_request.unlink()
|
||||
msg = "You cannot delete a purchase request which is not draft."
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
self.assertEqual(purchase_request.is_editable, False, "Should not be editable")
|
||||
purchase_request.button_draft()
|
||||
self.assertEqual(purchase_request.is_editable, True, "Should be editable")
|
||||
self.assertEqual(purchase_request.state, "draft", "Should be in state draft")
|
||||
purchase_request.button_to_approve()
|
||||
purchase_request.button_in_progress()
|
||||
self.assertEqual(
|
||||
purchase_request.state, "in_progress", "Should be in state in_progress"
|
||||
)
|
||||
self.assertEqual(purchase_request.is_editable, False, "Should not be editable")
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
purchase_request.unlink()
|
||||
msg = "You cannot delete a purchase request which is not draft."
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
purchase_request.button_draft()
|
||||
self.assertEqual(purchase_request.is_editable, True, "Should be editable")
|
||||
self.assertEqual(purchase_request.state, "draft", "Should be in state draft")
|
||||
purchase_request.button_to_approve()
|
||||
purchase_request.button_done()
|
||||
self.assertEqual(purchase_request.is_editable, False, "Should not be editable")
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
purchase_request.unlink()
|
||||
msg = "You cannot delete a purchase request which is not draft."
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
purchase_request.button_rejected()
|
||||
self.assertEqual(purchase_request.is_editable, False, "Should not be editable")
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_6").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line = self.purchase_request_line_obj.create(vals)
|
||||
purchase_request.button_approved()
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
|
||||
# It is required to have a picking type
|
||||
purchase_request.picking_type_id = False
|
||||
with self.assertRaisesRegex(UserError, "a Picking Type"):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request",
|
||||
active_ids=[purchase_request.id],
|
||||
).create(vals)
|
||||
purchase_request.picking_type_id = self.picking_type_id
|
||||
|
||||
# Picking type across all lines have to be the same
|
||||
purchase_request2 = purchase_request.copy(
|
||||
{"picking_type_id": self.picking_type_id.copy().id}
|
||||
)
|
||||
purchase_request2.button_approved()
|
||||
with self.assertRaisesRegex(UserError, "same Picking Type"):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=(purchase_request_line + purchase_request2.line_ids).ids,
|
||||
).create(vals)
|
||||
|
||||
purchase_request2.picking_type_id = purchase_request.picking_type_id
|
||||
purchase_request2.group_id = self.env["procurement.group"].create({})
|
||||
with self.assertRaisesRegex(UserError, "different procurement group"):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=(purchase_request_line + purchase_request2.line_ids).ids,
|
||||
).create(vals)
|
||||
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
# Unlink purchase_lines from state approved
|
||||
with self.assertRaises(UserError):
|
||||
purchase_request_line.unlink()
|
||||
purchase = purchase_request_line.purchase_lines.order_id
|
||||
purchase.button_done()
|
||||
self.assertEqual(purchase.state, "done")
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
UserError, "The purchase has already been completed"
|
||||
):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line.id],
|
||||
).create(vals)
|
||||
|
||||
purchase_request_line._compute_purchase_state()
|
||||
# Error case purchase_order in state done
|
||||
with self.assertRaisesRegex(UserError, "has already been completed"):
|
||||
purchase.button_confirm()
|
||||
purchase.button_cancel()
|
||||
self.assertEqual(purchase.state, "cancel")
|
||||
purchase_request_line._compute_purchase_state()
|
||||
with self.assertRaisesRegex(
|
||||
exceptions.UserError,
|
||||
"You cannot delete a purchase request which is not draft",
|
||||
):
|
||||
purchase_request.unlink()
|
||||
purchase_request.button_draft()
|
||||
purchase_request.unlink()
|
||||
|
||||
def test_auto_reject(self):
|
||||
"""Tests if a Purchase Request is autorejected when all lines are
|
||||
cancelled."""
|
||||
purchase_request = self.purchase_request
|
||||
# Add a second line to the PR:
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_16").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
}
|
||||
self.purchase_request_line_obj.create(vals)
|
||||
lines = purchase_request.line_ids
|
||||
# Cancel one line:
|
||||
lines[0].do_cancel()
|
||||
self.assertNotEqual(
|
||||
purchase_request.state,
|
||||
"rejected",
|
||||
"Purchase Request should not have been rejected.",
|
||||
)
|
||||
# Cancel the second one:
|
||||
lines[1].do_cancel()
|
||||
self.assertEqual(
|
||||
purchase_request.state,
|
||||
"rejected",
|
||||
"Purchase Request should have been auto-rejected.",
|
||||
)
|
||||
|
||||
def test_pr_line_to_approve_allowed(self):
|
||||
request = self.purchase_request
|
||||
self.assertTrue(request.to_approve_allowed)
|
||||
|
||||
pr_lines = self.purchase_request.line_ids
|
||||
pr_lines.write({"product_qty": 0})
|
||||
self.assertFalse(request.to_approve_allowed)
|
||||
|
||||
pr_lines.write({"product_qty": 5})
|
||||
self.assertTrue(request.to_approve_allowed)
|
||||
|
||||
pr_lines.do_cancel()
|
||||
self.assertFalse(request.to_approve_allowed)
|
||||
|
||||
# Request has been automatically rejected
|
||||
request.button_draft()
|
||||
new_line = self.purchase_request_line_obj.create(
|
||||
{
|
||||
"product_id": self.env.ref("product.product_product_16").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 0.0,
|
||||
"request_id": request.id,
|
||||
}
|
||||
)
|
||||
pr_lines.do_cancel()
|
||||
self.assertFalse(request.to_approve_allowed)
|
||||
|
||||
new_line.write({"product_qty": 1})
|
||||
self.assertTrue(request.to_approve_allowed)
|
||||
request.line_ids.unlink()
|
||||
self.assertFalse(request.to_approve_allowed)
|
||||
|
||||
def test_empty_purchase_request(self):
|
||||
pr = self.purchase_request
|
||||
pr_lines = pr.line_ids
|
||||
pr_lines.write({"product_qty": 0})
|
||||
|
||||
with self.assertRaises(UserError):
|
||||
self.purchase_request.button_to_approve()
|
||||
|
||||
pr_lines.write({"product_qty": 4})
|
||||
pr.button_to_approve()
|
||||
self.assertEqual(pr.state, "to_approve")
|
||||
|
||||
def test_default_picking_type(self):
|
||||
with Form(self.purchase_request_obj) as f:
|
||||
f.name = "Test Purchase"
|
||||
f.requested_by = self.env.user
|
||||
f.save()
|
||||
|
||||
def test_copy_purchase_request(self):
|
||||
purchase_request = self.purchase_request
|
||||
# Add a second line to the PR:
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_16").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
}
|
||||
self.purchase_request_line_obj.create(vals)
|
||||
purchase_request_copy = purchase_request.copy()
|
||||
self.assertEqual(purchase_request_copy.state, "draft")
|
||||
|
||||
def test_raise_error(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_16").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line = self.purchase_request_line_obj.create(vals)
|
||||
self.assertEqual(purchase_request.state, "draft")
|
||||
# create purchase order from draft state
|
||||
with self.assertRaises(UserError):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line.id],
|
||||
).create(vals)
|
||||
purchase_request.button_done()
|
||||
# create purchase order from done state
|
||||
self.assertEqual(purchase_request.state, "done")
|
||||
purchase_request_line._compute_is_editable()
|
||||
with self.assertRaisesRegex(UserError, "already been completed"):
|
||||
self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line.id],
|
||||
).create(vals)
|
||||
# Change product_qty to negative
|
||||
purchase_request_line.write({"product_qty": -6})
|
||||
purchase_request.button_approved()
|
||||
self.assertEqual(purchase_request.state, "approved")
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line.id]
|
||||
).create(vals)
|
||||
with self.assertRaisesRegex(UserError, "Enter a positive quantity"):
|
||||
wiz_id.make_purchase_order()
|
||||
|
||||
def test_purchase_request_unlink(self):
|
||||
pr = self.purchase_request
|
||||
pr_lines = pr.line_ids
|
||||
|
||||
pr.button_to_approve()
|
||||
self.assertEqual(pr.state, "to_approve", "Should be in state to_approve")
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
pr_lines.unlink()
|
||||
msg = (
|
||||
"You can only delete a purchase request line "
|
||||
"if the purchase request is in draft state."
|
||||
)
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
pr.button_in_progress()
|
||||
self.assertEqual(pr.state, "in_progress", "Should be in state in_progress")
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
pr_lines.unlink()
|
||||
msg = (
|
||||
"You can only delete a purchase request line "
|
||||
"if the purchase request is in draft state."
|
||||
)
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
pr.button_done()
|
||||
self.assertEqual(pr.state, "done", "Should be in state done")
|
||||
with self.assertRaises(exceptions.UserError) as e:
|
||||
pr_lines.unlink()
|
||||
msg = (
|
||||
"You can only delete a purchase request line "
|
||||
"if the purchase request is in draft state."
|
||||
)
|
||||
self.assertIn(msg, e.exception.args[0])
|
||||
pr.button_draft()
|
||||
self.assertEqual(pr.state, "draft", "Should be in state draft")
|
||||
pr_lines.unlink()
|
||||
|
|
@ -0,0 +1,434 @@
|
|||
# Copyright 2018-2019 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import SUPERUSER_ID
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestPurchaseRequestToRfq(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPurchaseRequestToRfq, self).setUp()
|
||||
self.purchase_request = self.env["purchase.request"]
|
||||
self.purchase_request_line = self.env["purchase.request.line"]
|
||||
self.wiz = self.env["purchase.request.line.make.purchase.order"]
|
||||
self.purchase_order = self.env["purchase.order"]
|
||||
vendor = self.env["res.partner"].create({"name": "Partner #2"})
|
||||
self.service_product = self.env["product.product"].create(
|
||||
{"name": "Product Service Test", "type": "service"}
|
||||
)
|
||||
self.product_product = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product Product Test",
|
||||
"type": "product",
|
||||
"description_purchase": "Test Description",
|
||||
}
|
||||
)
|
||||
self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor.id,
|
||||
"product_tmpl_id": self.service_product.product_tmpl_id.id,
|
||||
}
|
||||
)
|
||||
self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor.id,
|
||||
"product_tmpl_id": self.product_product.product_tmpl_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_purchase_request_allocation(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.product_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request2 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.product_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line.create(vals)
|
||||
purchase_request1.button_approved()
|
||||
purchase_request2.button_approved()
|
||||
purchase_request1.action_view_purchase_request_line()
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line1.id, purchase_request_line2.id],
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
purchase_request1.action_view_purchase_order()
|
||||
po_line = purchase_request_line1.purchase_lines[0]
|
||||
# Add unit price in PO Line
|
||||
po_line.write({"price_unit": 10})
|
||||
purchase = po_line.order_id
|
||||
purchase.order_line.action_open_request_line_tree_view()
|
||||
purchase.button_confirm()
|
||||
purchase_request1.action_view_stock_picking()
|
||||
self.assertEqual(purchase_request_line1.qty_in_progress, 2.0)
|
||||
self.assertEqual(purchase_request_line2.qty_in_progress, 2.0)
|
||||
picking = purchase.picking_ids[0]
|
||||
|
||||
# Check the move
|
||||
move = picking.move_ids
|
||||
self.assertEqual(move.purchase_request_ids, purchase_request1)
|
||||
# Do a move split/merge roundtrip and check that the allocatable
|
||||
# quantity remains the same.
|
||||
self.assertEqual(
|
||||
sum(move.purchase_request_allocation_ids.mapped("open_product_qty")), 4
|
||||
)
|
||||
split_move = self.env["stock.move"].create(move._split(1))
|
||||
split_move._action_confirm(merge=False)
|
||||
self.assertEqual(split_move.purchase_request_ids, purchase_request1)
|
||||
# The quantity of 4 is now split between the two moves
|
||||
self.assertEqual(
|
||||
sum(move.purchase_request_allocation_ids.mapped("open_product_qty")), 3
|
||||
)
|
||||
self.assertEqual(
|
||||
sum(split_move.purchase_request_allocation_ids.mapped("open_product_qty")),
|
||||
1,
|
||||
)
|
||||
split_move._merge_moves(merge_into=move)
|
||||
self.assertFalse(split_move.exists())
|
||||
self.assertEqual(
|
||||
sum(move.purchase_request_allocation_ids.mapped("open_product_qty")), 4
|
||||
)
|
||||
# Reset reserved quantities messed up by the roundtrip
|
||||
move._do_unreserve()
|
||||
move._action_assign()
|
||||
|
||||
picking.move_line_ids[0].write({"qty_done": 2.0})
|
||||
backorder_wiz_id = picking.button_validate()
|
||||
common.Form(
|
||||
self.env[backorder_wiz_id["res_model"]].with_context(
|
||||
**backorder_wiz_id["context"]
|
||||
)
|
||||
).save().process()
|
||||
request_lines = purchase_request_line1 + purchase_request_line2
|
||||
self.assertEqual(sum(request_lines.mapped("qty_done")), 2.0)
|
||||
|
||||
backorder_picking = purchase.picking_ids.filtered(lambda p: p.id != picking.id)
|
||||
backorder_picking.move_line_ids[0].write({"qty_done": 1.0})
|
||||
backorder_wiz_id2 = backorder_picking.button_validate()
|
||||
common.Form(
|
||||
self.env[backorder_wiz_id2["res_model"]].with_context(
|
||||
**backorder_wiz_id2["context"]
|
||||
)
|
||||
).save().process()
|
||||
|
||||
self.assertEqual(sum(request_lines.mapped("qty_done")), 3.0)
|
||||
for pick in purchase.picking_ids:
|
||||
if pick.state == "assigned":
|
||||
pick.action_cancel()
|
||||
self.assertEqual(sum(request_lines.mapped("qty_cancelled")), 1.0)
|
||||
self.assertEqual(sum(request_lines.mapped("pending_qty_to_receive")), 1.0)
|
||||
|
||||
def test_purchase_request_allocation_services(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"assigned_to": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.service_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request1.button_approved()
|
||||
purchase_request1.action_view_purchase_request_line()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line1.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
purchase_request1.action_view_purchase_order()
|
||||
po_line = purchase_request_line1.purchase_lines[0]
|
||||
# Add unit price in PO Line
|
||||
po_line.write({"price_unit": 10})
|
||||
purchase = po_line.order_id
|
||||
purchase.button_confirm()
|
||||
self.assertEqual(purchase_request_line1.qty_in_progress, 2.0)
|
||||
# manually set in the PO line
|
||||
po_line.write({"qty_received": 0.5})
|
||||
self.assertEqual(purchase_request_line1.qty_done, 0.5)
|
||||
purchase.button_cancel()
|
||||
self.assertEqual(purchase_request_line1.qty_cancelled, 1.5)
|
||||
self.assertEqual(purchase_request_line1.pending_qty_to_receive, 1.5)
|
||||
# Case revieve 2 product
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"assigned_to": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request2 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": self.service_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request2.button_approved()
|
||||
purchase_request2.action_view_purchase_request_line()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line2.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
(purchase_request1 + purchase_request2).action_view_purchase_order()
|
||||
po_line = purchase_request_line2.purchase_lines[0]
|
||||
purchase2 = po_line.order_id
|
||||
purchase2.button_confirm()
|
||||
self.assertEqual(purchase_request_line2.qty_in_progress, 2.0)
|
||||
purchase_request1.action_view_stock_picking()
|
||||
# manually set in the PO line
|
||||
po_line.write({"qty_received": 2.0})
|
||||
self.assertEqual(purchase_request_line2.qty_done, 2.0)
|
||||
|
||||
def test_purchase_request_allocation_min_qty(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.product_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
# add a vendor
|
||||
vendor1 = self.env.ref("base.res_partner_1")
|
||||
self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor1.id,
|
||||
"product_tmpl_id": self.product_product.product_tmpl_id.id,
|
||||
"min_qty": 8,
|
||||
}
|
||||
)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request1.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line1.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[0].open_product_qty,
|
||||
2.0,
|
||||
)
|
||||
|
||||
def test_purchase_request_stock_allocation(self):
|
||||
product = self.env.ref("product.product_product_6")
|
||||
product.uom_po_id = self.env.ref("uom.product_uom_dozen")
|
||||
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 12.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_dozen").id,
|
||||
"product_qty": 1,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line1.id, purchase_request_line2.id],
|
||||
).create(vals)
|
||||
# Create PO
|
||||
wiz_id.make_purchase_order()
|
||||
po_line = purchase_request_line1.purchase_lines[0]
|
||||
self.assertEqual(po_line.product_qty, 2, "Quantity should be 2")
|
||||
self.assertEqual(
|
||||
po_line.product_uom,
|
||||
self.env.ref("uom.product_uom_dozen"),
|
||||
"The purchase UoM should be Dozen(s).",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[
|
||||
0
|
||||
].requested_product_uom_qty,
|
||||
12.0,
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line2.purchase_request_allocation_ids[
|
||||
0
|
||||
].requested_product_uom_qty,
|
||||
1.0,
|
||||
)
|
||||
purchase = po_line.order_id
|
||||
# Cancel PO allocation requested quantity is set to 0.
|
||||
purchase.button_cancel()
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[0].open_product_qty,
|
||||
0,
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line2.purchase_request_allocation_ids[0].open_product_qty,
|
||||
0,
|
||||
)
|
||||
# Set to draft allocation requested quantity is set
|
||||
purchase.button_draft()
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[0].open_product_qty,
|
||||
12.0,
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line2.purchase_request_allocation_ids[0].open_product_qty,
|
||||
1.0,
|
||||
)
|
||||
purchase.button_confirm()
|
||||
picking = purchase.picking_ids[0]
|
||||
picking.move_line_ids[0].write({"qty_done": 24.0})
|
||||
picking.button_validate()
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[
|
||||
0
|
||||
].allocated_product_qty,
|
||||
purchase_request_line1.purchase_request_allocation_ids[
|
||||
0
|
||||
].requested_product_uom_qty,
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line2.purchase_request_allocation_ids[
|
||||
0
|
||||
].allocated_product_qty,
|
||||
purchase_request_line2.purchase_request_allocation_ids[
|
||||
0
|
||||
].requested_product_uom_qty,
|
||||
)
|
||||
|
||||
def test_purchase_request_stock_allocation_unlink(self):
|
||||
product = self.env.ref("product.product_product_6")
|
||||
product.uom_po_id = self.env.ref("uom.product_uom_dozen")
|
||||
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 12.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line1.id]
|
||||
).create(vals)
|
||||
# Create PO
|
||||
wiz_id.make_purchase_order()
|
||||
po_line = purchase_request_line1.purchase_lines[0]
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchase_request_allocation_ids[
|
||||
0
|
||||
].requested_product_uom_qty,
|
||||
12.0,
|
||||
)
|
||||
purchase = po_line.order_id
|
||||
purchase.button_cancel()
|
||||
# Delete PO: allocation and Purchase Order Lines are unlinked from PRL
|
||||
purchase.unlink()
|
||||
self.assertEqual(len(purchase_request_line1.purchase_lines), 0)
|
||||
self.assertEqual(len(purchase_request_line1.purchase_request_allocation_ids), 0)
|
||||
|
||||
def test_onchange_product_id(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.product_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line.create(vals)
|
||||
purchase_request_line1.onchange_product_id()
|
||||
|
||||
def test_empty_records_for_company_constraint(self):
|
||||
self.assertFalse(self.env["stock.move"]._check_company_purchase_request())
|
||||
|
||||
def test_supplier_assignment(self):
|
||||
"""Suppliers are not assigned across the company boundary"""
|
||||
product = self.env.ref("product.product_product_6")
|
||||
product.seller_ids.unlink()
|
||||
purchase_request = self.purchase_request.create(
|
||||
{
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
}
|
||||
)
|
||||
purchase_request_line = self.purchase_request_line.create(
|
||||
{
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 12.0,
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
}
|
||||
)
|
||||
# A supplier from another company is not assigned
|
||||
vendor3 = self.env["res.partner"].create({"name": "Partner #3"})
|
||||
supinfo = self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor3.id,
|
||||
"product_tmpl_id": product.product_tmpl_id.id,
|
||||
"company_id": self.env.ref("stock.res_company_1").id,
|
||||
}
|
||||
)
|
||||
self.assertFalse(purchase_request_line.supplier_id)
|
||||
# A supplierinfo of a matching company leads to supplier assignment
|
||||
vendor4 = self.env["res.partner"].create({"name": "Partner #4"})
|
||||
supinfo = self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor4.id,
|
||||
"product_tmpl_id": product.product_tmpl_id.id,
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
}
|
||||
)
|
||||
self.assertEqual(purchase_request_line.supplier_id, vendor4)
|
||||
supinfo.unlink()
|
||||
self.assertFalse(purchase_request_line.supplier_id)
|
||||
# A supplierinfo without company leads to supplier assignment as well
|
||||
self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor4.id,
|
||||
"product_tmpl_id": product.product_tmpl_id.id,
|
||||
"company_id": False,
|
||||
}
|
||||
)
|
||||
self.assertEqual(purchase_request_line.supplier_id, vendor4)
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
# Copyright 2018-2019 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import fields
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestPurchaseRequestProcurement(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPurchaseRequestProcurement, self).setUp()
|
||||
|
||||
# Get required Model
|
||||
self.pr_model = self.env["purchase.request"]
|
||||
self.prl_model = self.env["purchase.request.line"]
|
||||
self.product_uom_model = self.env["uom.uom"]
|
||||
self.location = self.env.ref("stock.stock_location_stock")
|
||||
self.customer_location = self.env.ref("stock.stock_location_customers")
|
||||
|
||||
# Get required Model data
|
||||
self.product_1 = self.env.ref("product.product_product_16")
|
||||
self.product_1.purchase_request = True
|
||||
self.route_buy = self.env.ref("purchase_stock.route_warehouse0_buy")
|
||||
self.rule_buy = self.route_buy.rule_ids.filtered(
|
||||
lambda rule: rule.location_dest_id == self.location
|
||||
)
|
||||
# Create Supplier
|
||||
self.supplier = self.env["res.partner"].create(
|
||||
{"name": "Supplier", "is_company": True, "company_id": False}
|
||||
)
|
||||
|
||||
# Add supplier to product_1
|
||||
self.product_1.write(
|
||||
{
|
||||
"seller_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"partner_id": self.supplier.id,
|
||||
"price": 100.0,
|
||||
"company_id": False,
|
||||
},
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
def _procurement_group_run(self, origin, product, qty):
|
||||
"""Create an outgoing move and procure it"""
|
||||
move = self.env["stock.move"].create(
|
||||
{
|
||||
"reservation_date": fields.Datetime.now(),
|
||||
"location_dest_id": self.customer_location.id,
|
||||
"location_id": self.location.id,
|
||||
"name": product.name,
|
||||
"origin": origin,
|
||||
"procure_method": "make_to_order",
|
||||
"product_id": product.id,
|
||||
"product_uom": product.uom_id.id,
|
||||
"product_uom_qty": qty,
|
||||
"route_ids": [(4, self.route_buy.id)],
|
||||
}
|
||||
)
|
||||
move._action_confirm()
|
||||
return move
|
||||
|
||||
def test_orderpoint(self):
|
||||
"""Purchase request quantity is reflected in the orderpoint forecasted qty"""
|
||||
qty = 5
|
||||
orderpoint = self.env["stock.warehouse.orderpoint"].create(
|
||||
{
|
||||
"name": __name__,
|
||||
"warehouse_id": self.env.ref("stock.warehouse0").id,
|
||||
"location_id": self.location.id,
|
||||
"product_id": self.product_1.id,
|
||||
"product_min_qty": 1,
|
||||
"product_max_qty": qty,
|
||||
}
|
||||
)
|
||||
self.env["procurement.group"].run_scheduler()
|
||||
self.assertEqual(
|
||||
self.env["purchase.request"]
|
||||
.search([("product_id", "=", self.product_1.id)])
|
||||
.line_ids.product_qty,
|
||||
qty,
|
||||
)
|
||||
self.assertEqual(orderpoint.qty_forecast, qty)
|
||||
|
||||
def test_procure_purchase_request(self):
|
||||
"""A request line is created from a procured move"""
|
||||
move = self._procurement_group_run(
|
||||
"Test Purchase Request Procurement",
|
||||
self.product_1,
|
||||
10,
|
||||
)
|
||||
self.assertTrue(move.created_purchase_request_line_id)
|
||||
pr = move.created_purchase_request_line_id.request_id
|
||||
self.assertTrue(pr.to_approve_allowed)
|
||||
self.assertEqual(pr.origin, "Test Purchase Request Procurement")
|
||||
|
||||
# Now cancel the move. An activity is created on the request.
|
||||
# Even if the activity type was deleted
|
||||
activity = self.env.ref("mail.mail_activity_data_todo")
|
||||
self.env["mail.activity"].search(
|
||||
[("activity_type_id", "=", activity.id)]
|
||||
).unlink()
|
||||
self.assertFalse(move.created_purchase_request_line_id.request_id.activity_ids)
|
||||
move._action_cancel()
|
||||
self.assertTrue(move.created_purchase_request_line_id.request_id.activity_ids)
|
||||
|
||||
def test_procure_purchase_request_with_fixed_group(self):
|
||||
"""Existing requests are reused depending on group settings.
|
||||
|
||||
Having a procurement rule with fixed group settings, existing
|
||||
purchase requests are only matched during procurement
|
||||
if the groups correspond.
|
||||
"""
|
||||
group = self.env["procurement.group"].create({})
|
||||
self.rule_buy.write(
|
||||
{
|
||||
"group_id": group.id,
|
||||
"group_propagation_option": "fixed",
|
||||
}
|
||||
)
|
||||
move = self._procurement_group_run(
|
||||
False,
|
||||
self.product_1,
|
||||
10,
|
||||
)
|
||||
pr = move.created_purchase_request_line_id.request_id
|
||||
self.assertEqual(pr.group_id, group)
|
||||
|
||||
# A second procurement reuses the same request
|
||||
move2 = self._procurement_group_run(
|
||||
"Test Origin",
|
||||
self.product_1,
|
||||
10,
|
||||
)
|
||||
pr2 = move2.created_purchase_request_line_id.request_id
|
||||
self.assertEqual(pr2, pr)
|
||||
|
||||
# Reset the group on the first purchase request
|
||||
pr.group_id = self.env["procurement.group"].create({})
|
||||
|
||||
# Because of the group difference, the request is not reused
|
||||
move3 = self._procurement_group_run("Test with group", self.product_1, 10)
|
||||
pr3 = move3.created_purchase_request_line_id.request_id
|
||||
self.assertEqual(pr3.group_id, group)
|
||||
self.assertNotEqual(pr3, pr)
|
||||
|
||||
def test_origin(self):
|
||||
"""The purchase request origin reflects the origins of each procurement"""
|
||||
move = self._procurement_group_run("Test Origin", self.product_1, 10)
|
||||
pr = move.created_purchase_request_line_id.request_id
|
||||
self.assertEqual(pr.origin, "Test Origin")
|
||||
|
||||
# A new procurement origin is added to the request origin
|
||||
move2 = self._procurement_group_run("Test, Split", self.product_1, 10)
|
||||
self.assertEqual(move2.created_purchase_request_line_id.request_id, pr)
|
||||
self.assertEqual(pr.origin, "Test Origin, Test, Split")
|
||||
|
||||
# An empty procurement origin is not added to the request origin
|
||||
move3 = self._procurement_group_run(False, self.product_1, 10)
|
||||
self.assertEqual(move3.created_purchase_request_line_id.request_id, pr)
|
||||
self.assertEqual(pr.origin, "Test Origin, Test, Split")
|
||||
|
||||
# An existing procurement origin is not added to the request origin
|
||||
move4 = self._procurement_group_run("Split", self.product_1, 10)
|
||||
self.assertEqual(move4.created_purchase_request_line_id.request_id, pr)
|
||||
self.assertEqual(pr.origin, "Test Origin, Test, Split")
|
||||
|
|
@ -0,0 +1,424 @@
|
|||
# Copyright 2018-2019 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import SUPERUSER_ID
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestPurchaseRequestToRfq(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPurchaseRequestToRfq, self).setUp()
|
||||
self.purchase_request_obj = self.env["purchase.request"]
|
||||
self.purchase_request_line_obj = self.env["purchase.request.line"]
|
||||
self.wiz = self.env["purchase.request.line.make.purchase.order"]
|
||||
self.purchase_order = self.env["purchase.order"]
|
||||
vendor = self.env["res.partner"].create({"name": "Partner #2"})
|
||||
self.service_product = self.env["product.product"].create(
|
||||
{"name": "Product Service Test", "type": "service"}
|
||||
)
|
||||
self.env["product.supplierinfo"].create(
|
||||
{
|
||||
"partner_id": vendor.id,
|
||||
"product_tmpl_id": self.service_product.product_tmpl_id.id,
|
||||
}
|
||||
)
|
||||
self.product_product = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product Product Test",
|
||||
"type": "product",
|
||||
"description_purchase": "Test Description",
|
||||
}
|
||||
)
|
||||
|
||||
def test_wizard_default_get(self):
|
||||
# Check that correct create items by purchase.request
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"line_ids": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.env.ref("product.product_product_13").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
purchase_request1 = self.purchase_request_obj.create(vals)
|
||||
purchase_request1.button_approved()
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"line_ids": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.env.ref("product.product_product_13").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 2.0,
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
purchase_request2 = self.purchase_request_obj.create(vals)
|
||||
purchase_request2.button_approved()
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[
|
||||
purchase_request1.mapped("line_ids").id,
|
||||
purchase_request2.mapped("line_ids").id,
|
||||
],
|
||||
).create(vals)
|
||||
self.assertEqual(
|
||||
(purchase_request1 | purchase_request2).mapped("line_ids"),
|
||||
wiz_id.item_ids.mapped("line_id"),
|
||||
"Should have same purchase request lines",
|
||||
)
|
||||
|
||||
def test_purchase_request_to_purchase_rfq(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_13").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
"estimated_cost": 50.0,
|
||||
}
|
||||
purchase_request_line = self.purchase_request_line_obj.create(vals)
|
||||
purchase_request.button_to_approve()
|
||||
purchase_request.button_approved()
|
||||
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_12").id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line.id],
|
||||
active_id=purchase_request_line.id,
|
||||
).create(vals)
|
||||
for item in wiz_id.item_ids:
|
||||
if item.line_id.id == purchase_request_line.id:
|
||||
item.keep_estimated_cost = True
|
||||
wiz_id.make_purchase_order()
|
||||
purchase_order = purchase_request_line.purchase_lines.order_id
|
||||
self.assertTrue(
|
||||
len(purchase_request_line.purchase_lines), "Should have a purchase line"
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line.purchase_lines.product_id.id,
|
||||
purchase_request_line.product_id.id,
|
||||
"Should have same product",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line.purchase_lines.state,
|
||||
purchase_request_line.purchase_state,
|
||||
"Should have same state",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_order.order_line.price_total,
|
||||
purchase_request_line.estimated_cost,
|
||||
"Should have same price",
|
||||
)
|
||||
|
||||
def test_bug_is_editable_multiple_lines(self):
|
||||
# Check that reading multiple lines is still possible
|
||||
# https://github.com/OCA/purchase-workflow/pull/291
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_13").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
}
|
||||
purchase_request_line = self.purchase_request_line_obj.create(vals)
|
||||
request_lines = purchase_request_line + purchase_request_line.copy()
|
||||
request_lines.mapped("is_editable")
|
||||
|
||||
# Test also for onchanges on non created lines
|
||||
self.purchase_request_line_obj.new({}).is_editable
|
||||
|
||||
def test_purchase_request_to_purchase_rfq_minimum_order_qty(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request.id,
|
||||
"product_id": self.env.ref("product.product_product_8").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 1.0,
|
||||
}
|
||||
purchase_request_line = self.purchase_request_line_obj.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request_line.id],
|
||||
active_id=purchase_request_line.id,
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
self.assertTrue(
|
||||
len(purchase_request_line.purchase_lines), "Should have a purchase line"
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line.purchase_lines.product_id.id,
|
||||
purchase_request_line.product_id.id,
|
||||
"Should have same product",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line.purchase_lines.state,
|
||||
purchase_request_line.purchase_state,
|
||||
"Should have same state",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line.purchase_lines.product_qty,
|
||||
5,
|
||||
"The PO line should have the minimum order quantity.",
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line,
|
||||
purchase_request_line.purchase_lines.purchase_request_lines,
|
||||
"The PO should cross-reference to the purchase request.",
|
||||
)
|
||||
|
||||
def test_purchase_request_to_purchase_rfq_multiple_po(self):
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request2 = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": self.env.ref("product.product_product_6").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_dozen").id,
|
||||
"product_qty": 1.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": self.env.ref("product.product_product_6").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 1.0,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": self.product_product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 1.0,
|
||||
}
|
||||
purchase_request_line3 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request1.button_approved()
|
||||
purchase_request2.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[
|
||||
purchase_request_line1.id,
|
||||
purchase_request_line2.id,
|
||||
purchase_request_line3.id,
|
||||
],
|
||||
).create(vals)
|
||||
for item in wiz_id.item_ids:
|
||||
if item.line_id.id == purchase_request_line2.id:
|
||||
item.keep_description = True
|
||||
if item.line_id.id == purchase_request_line3.id:
|
||||
item.onchange_product_id()
|
||||
wiz_id.make_purchase_order()
|
||||
self.assertEqual(
|
||||
purchase_request_line1.purchased_qty, 1.0, "Should be a quantity of 1"
|
||||
)
|
||||
self.assertEqual(
|
||||
purchase_request_line2.purchased_qty, 1.0, "Should be a quantity of 1"
|
||||
)
|
||||
|
||||
def test_purchase_request_to_purchase_rfq_multiple_PO_purchaseUoM(self):
|
||||
product = self.env.ref("product.product_product_6")
|
||||
product.uom_po_id = self.env.ref("uom.product_uom_dozen")
|
||||
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request2 = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 12.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 12.0,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 1.0,
|
||||
}
|
||||
purchase_request_line3 = self.purchase_request_line_obj.create(vals)
|
||||
vals = {"supplier_id": self.env.ref("base.res_partner_1").id}
|
||||
purchase_request1.button_approved()
|
||||
purchase_request2.button_approved()
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[
|
||||
purchase_request_line1.id,
|
||||
purchase_request_line2.id,
|
||||
purchase_request_line3.id,
|
||||
],
|
||||
).create(vals)
|
||||
for item in wiz_id.item_ids:
|
||||
if item.line_id.id == purchase_request_line2.id:
|
||||
# PRL will be splitted into another POL to keep description
|
||||
item.keep_description = True
|
||||
wiz_id.make_purchase_order()
|
||||
po_line = purchase_request_line1.purchase_lines[0]
|
||||
self.assertEqual(po_line.product_qty, 1.09, "Quantity should be 1.09")
|
||||
self.assertEqual(
|
||||
po_line.product_uom,
|
||||
self.env.ref("uom.product_uom_dozen"),
|
||||
"The purchase UoM should be Dozen(s).",
|
||||
)
|
||||
|
||||
def test_purchase_request_to_rfq_minimum_order_qty_existing_po(self):
|
||||
# Define Supplier
|
||||
supplier = self.env.ref("base.res_partner_1")
|
||||
# Create Product Widget min_qty = 5
|
||||
product = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Widget",
|
||||
"type": "product",
|
||||
"seller_ids": [
|
||||
(0, 0, {"partner_id": supplier.id, "delay": 10, "min_qty": 5})
|
||||
],
|
||||
}
|
||||
)
|
||||
# Create Purchase Order with qty = 3 through Purchase Request
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request1 = self.purchase_request_obj.create(vals)
|
||||
vals = {
|
||||
"request_id": purchase_request1.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 3.0,
|
||||
}
|
||||
purchase_request_line1 = self.purchase_request_line_obj.create(vals)
|
||||
purchase_request1.button_approved()
|
||||
vals = {"supplier_id": supplier.id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line1.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
# The planned date is taken from the request, not from the supplier
|
||||
self.assertEqual(
|
||||
purchase_request_line1.date_required.day,
|
||||
purchase_request_line1.purchase_lines.date_planned.day,
|
||||
)
|
||||
po = purchase_request_line1.purchase_lines[0].order_id
|
||||
# Create Purchase Request
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
}
|
||||
purchase_request2 = self.purchase_request_obj.create(vals)
|
||||
# Create Purchase Request Line qty = 3
|
||||
|
||||
vals = {
|
||||
"request_id": purchase_request2.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 3.0,
|
||||
}
|
||||
purchase_request_line2 = self.purchase_request_line_obj.create(vals)
|
||||
# Validate
|
||||
purchase_request2.button_approved()
|
||||
# Create RFQ to Previous PO
|
||||
vals = {"supplier_id": supplier.id, "purchase_order_id": po.id}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line", active_ids=[purchase_request_line2.id]
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
# Check Purchase qty should be 6
|
||||
po_line = purchase_request_line2.purchase_lines[0]
|
||||
# Add unit price in PO Line
|
||||
po_line.write({"price_unit": 10})
|
||||
self.assertEqual(po_line.product_qty, 6.0, "Quantity should be 6")
|
||||
# auto change state to done
|
||||
po_line.order_id.button_confirm()
|
||||
picking = po_line.order_id.picking_ids[0]
|
||||
picking.move_line_ids[0].write({"qty_done": 6.0})
|
||||
picking.button_validate()
|
||||
|
||||
def _setup_analytic_distribution(self):
|
||||
analytic_plan = self.env["account.analytic.plan"].create(
|
||||
{"name": "Plan Test", "company_id": False}
|
||||
)
|
||||
analytic_account = self.env["account.analytic.account"].create(
|
||||
{"name": "default", "plan_id": analytic_plan.id}
|
||||
)
|
||||
return {str(analytic_account.id): 100}
|
||||
|
||||
def test_purchase_request_to_purchase_order_analytic_data_propagation(self):
|
||||
analytic_distribution = self._setup_analytic_distribution()
|
||||
vals = {
|
||||
"picking_type_id": self.env.ref("stock.picking_type_in").id,
|
||||
"requested_by": SUPERUSER_ID,
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.env.ref("product.product_product_10").id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_unit").id,
|
||||
"product_qty": 5.0,
|
||||
"analytic_distribution": analytic_distribution,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
purchase_request = self.purchase_request_obj.create(vals)
|
||||
purchase_request.button_to_approve()
|
||||
purchase_request.button_approved()
|
||||
supplier = self.env.ref("base.res_partner_12")
|
||||
vals = {
|
||||
"supplier_id": supplier.id,
|
||||
}
|
||||
wiz_id = self.wiz.with_context(
|
||||
active_model="purchase.request.line",
|
||||
active_ids=[purchase_request["line_ids"][0].id],
|
||||
active_id=purchase_request["line_ids"][0].id,
|
||||
).create(vals)
|
||||
wiz_id.make_purchase_order()
|
||||
po_line = purchase_request["line_ids"][0].purchase_lines[0]
|
||||
self.assertEqual(po_line.analytic_distribution, analytic_distribution)
|
||||
Loading…
Add table
Add a link
Reference in a new issue