Skip to content

Commit

Permalink
[ADD] /apply_reward to apply claimable rewards to cart
Browse files Browse the repository at this point in the history
  • Loading branch information
marielejeune committed Oct 19, 2023
1 parent 2e5ed9e commit 94ab4b8
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
39 changes: 38 additions & 1 deletion shopinvader_api_sale_loyalty/routers/cart.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from odoo.addons.shopinvader_api_cart.routers import cart_router
from odoo.addons.shopinvader_api_cart.schemas import CartTransaction

from ..schemas import CartResponse, LoyaltyCardInput
from ..schemas import CartResponse, LoyaltyCardInput, LoyaltyRewardInput


@cart_router.post("/apply_coupon")
Expand All @@ -33,6 +33,20 @@ def apply_coupon(
return CartResponse.from_cart(cart) if cart else None


@cart_router.post("/apply_reward")
@cart_router.post("/apply_reward/{cart_uuid}")
def apply_reward(
data: LoyaltyRewardInput,
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated["ResPartner", Depends(authenticated_partner)],
cart_uuid: str | None = None,
) -> CartResponse | None:
cart = env["sale.order"]._find_open_cart(partner.id, cart_uuid)
if cart:
env["shopinvader_api_cart.service.helper"]._apply_reward(cart, data)
return CartResponse.from_cart(cart) if cart else None


class ShopinvaderApiCartServiceHelper(models.AbstractModel):
_inherit = "shopinvader_api_cart.service.helper"

Expand Down Expand Up @@ -111,6 +125,29 @@ def _apply_coupon(self, cart: "SaleOrder", data: LoyaltyCardInput):
).action_apply()
return cart

# Apply claimable reward
def _apply_reward(self, cart: "SaleOrder", data: LoyaltyRewardInput):
"""
Try to apply the given reward.
Raise an error if there is a choice between free products
and the chosen product is not specified.
"""
cart._update_programs_and_rewards()
reward = self.env["loyalty.reward"].browse(data.reward_id)
product_id = self._check_free_reward_product(reward, data.free_product_id)
return (
self.env["sale.loyalty.reward.wizard"]
.create(
{
"order_id": cart.id,
"selected_reward_id": data.reward_id,
"selected_product_id": product_id if product_id else None,
}
)
.action_apply()
)

# Apply automatic rewards at cart updates
def _apply_automatic_rewards(self, cart: SaleOrder):
claimable_rewards = cart._get_claimable_rewards()
Expand Down
2 changes: 1 addition & 1 deletion shopinvader_api_sale_loyalty/schemas/loyalty_reward.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ def from_loyalty_reward(cls, odoo_rec):


class LoyaltyRewardInput(StrictExtendableBaseModel):
reward_id: int | None = None
reward_id: int
free_product_id: int | None = None
2 changes: 1 addition & 1 deletion shopinvader_api_sale_loyalty/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from . import test_apply_coupon
from . import test_apply_coupon_or_reward
from . import test_get_rewards
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ def test_program_auto_reward_choice(self):
-> when updating the cart, the reward is not automatically applied
as there are several rewards linked to the program.
But the rewards are in the CartResponse, under claimable_rewards
Then calling /apply_reward applies the reward and removes the rewards
from the CartResponse
"""
program = self._create_program_choice_reward_auto(self.product_A)
with self._create_test_client(router=cart_router) as test_client:
Expand All @@ -462,6 +465,23 @@ def test_program_auto_reward_choice(self):
set(program.reward_ids.ids),
)

# Apply the reward
with self._create_test_client(router=cart_router) as test_client:
data = {"reward_id": claimable_rewards[0]["id"]}
response: Response = test_client.post(
"/apply_reward", content=json.dumps(data)
)
self.assertEqual(response.status_code, 200)
res = response.json()
self.assertEqual(
len(self.cart.order_line),
2,
"The promotion should have been applied",
)
self.assertEqual(
res["claimable_rewards"], [], "Rewards shouldn't be claimable anymore"
)

def test_program_with_code_product_choice(self):
"""
Create a new program with code that gives you the choice: if A is bought,
Expand Down Expand Up @@ -519,6 +539,9 @@ def test_program_auto_product_choice(self):
-> when updating the cart, the reward is not automatically applied
as there is a choice to make.
When calling /apply_reward without specified product, the service fails.
When specifying the product, the reward is added.
"""
self.product_B.product_tag_ids = [(4, self.gift_product_tag.id)]
self.product_C.product_tag_ids = [(4, self.gift_product_tag.id)]
Expand Down Expand Up @@ -549,3 +572,28 @@ def test_program_auto_product_choice(self):
set(self.gift_product_tag.product_ids.ids),
"There should be a choice between 2 claimable free products.",
)

# Try applying reward without specifying the product
with self._create_test_client(
router=cart_router
) as test_client, self.assertRaisesRegex(
UserError, "Several free products available. Please specify one."
):
data = {"reward_id": claimable_rewards[0]["id"]}
test_client.post("/apply_reward", content=json.dumps(data))

# Apply the reward specifying the product
with self._create_test_client(router=cart_router) as test_client:
data = {
"reward_id": claimable_rewards[0]["id"],
"free_product_id": self.product_C.id,
}
response = test_client.post("/apply_reward", content=json.dumps(data))
self.assertEqual(response.status_code, 200)
res = response.json()
self.assertEqual(
len(self.cart.order_line),
2,
"The promotion should have been applied",
)
self.assertEqual(res["claimable_rewards"], [])

0 comments on commit 94ab4b8

Please sign in to comment.