Skip to content

Commit

Permalink
[WIP][ADD] shopinvader_api_sale_loyalty: FastAPI services to apply co…
Browse files Browse the repository at this point in the history
…upons
  • Loading branch information
marielejeune committed Oct 18, 2023
1 parent 10a15b4 commit 3c6d596
Show file tree
Hide file tree
Showing 32 changed files with 1,899 additions and 0 deletions.
6 changes: 6 additions & 0 deletions setup/shopinvader_api_sale_loyalty/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
71 changes: 71 additions & 0 deletions shopinvader_api_sale_loyalty/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
====================
Shopinvader API Cart
====================

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-shopinvader%2Fodoo--shopinvader-lightgray.png?logo=github
:target: https://github.com/shopinvader/odoo-shopinvader/tree/16.0/shopinvader_api_cart
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

This addon adds a web API on top of the sale.order model to ease the creation of
sale orders from Web frontend. The API is designed to work with the shopinvader-js-cart library
see (https://github.com/shopinvader/shopinvader-js-cart)

**Table of contents**

.. contents::
:local:

Changelog
=========

16.0.1.0.2 (2023-10-13)
~~~~~~~~~~~~~~~~~~~~~~~

**Misc**

- `#1422 <https://github.com/shopinvader/odoo-shopinvader/issues/1422>`_

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/shopinvader/odoo-shopinvader/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/shopinvader/odoo-shopinvader/issues/new?body=module:%20shopinvader_api_cart%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* ACSONE SA/NV

Contributors
~~~~~~~~~~~~

* Laurent Mignon <[email protected]>
* Stéphane Bidoul <[email protected]>
* Marie Lejeune <[email protected]>

Maintainers
~~~~~~~~~~~

This module is part of the `shopinvader/odoo-shopinvader <https://github.com/shopinvader/odoo-shopinvader/tree/16.0/shopinvader_api_cart>`_ project on GitHub.

You are welcome to contribute.
2 changes: 2 additions & 0 deletions shopinvader_api_sale_loyalty/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import routers
37 changes: 37 additions & 0 deletions shopinvader_api_sale_loyalty/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2022 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Shopinvader API Sale Loyalty",
"summary": """
FastAPI services to add coupons and loyalties to carts.""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"depends": [
"sale_loyalty",
"shopinvader_api_cart",
"pydantic",
"extendable",
"fastapi",
"extendable_fastapi",
],
"data": [
"security/groups.xml",
"security/acl_loyalty_card.xml",
"security/acl_loyalty_program.xml",
"security/acl_loyalty_reward.xml",
"security/acl_loyalty_rule.xml",
"security/acl_product_tag.xml",
"security/acl_sale_order_coupon_points.xml",
"security/acl_sale_loyalty_reward_wizard.xml",
],
"external_dependencies": {
"python": [
"fastapi",
"pydantic>=2.0.0",
"extendable-pydantic>=1.2.0",
]
},
}
2 changes: 2 additions & 0 deletions shopinvader_api_sale_loyalty/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import shopinvader_api_cart_service_helper
from . import sale_order
63 changes: 63 additions & 0 deletions shopinvader_api_sale_loyalty/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models


class SaleOrder(models.Model):
_inherit = "sale.order"

# TODO: needed?
reward_amount_tax_incl = fields.Float(compute="_compute_reward_total_tax_incl")
promo_codes = fields.Char(compute="_compute_promo_codes")
generated_coupon_ids = fields.One2many(
"loyalty.card",
"order_id",
"Generated Coupons",
help="The coupons generated from this order.",
)
program_ids = fields.Many2many(
"loyalty.program", string="Applied programs", compute="_compute_programs"
)

def _get_reward_lines(self):
self.ensure_one()
return self.order_line.filtered("is_reward_line")

@api.depends("order_line")
def _compute_reward_total_tax_incl(self):
for order in self:
reward_amount_tax_incl = 0
for line in order._get_reward_lines():
if line.reward_id.reward_type != "product":
reward_amount_tax_incl += line.price_subtotal
else:
# Free product are 'regular' product lines with a price_unit of 0
reward_amount_tax_incl -= (
line.product_id.lst_price * line.product_uom_qty
)
order.reward_amount_tax_incl = reward_amount_tax_incl

@api.depends("order_line", "applied_coupon_ids", "code_enabled_rule_ids")
def _compute_promo_codes(self):
for order in self:
codes = order.applied_coupon_ids.mapped(
"code"
) + order.code_enabled_rule_ids.mapped("code")
if codes:
order.promo_codes = str(codes) # stock the list of codes in a string
else:
order.promo_codes = "[]"

@api.depends("order_line", "applied_coupon_ids", "code_enabled_rule_ids")
def _compute_programs(self):
self.program_ids = self.env["loyalty.program"]
for order in self:
# Consider claimable rewards
order._update_programs_and_rewards()
res = order._get_claimable_rewards()
for coupon, _ in res.items():
order.program_ids |= coupon.program_id

# Consider applied rewards
programs = order._get_reward_lines().mapped("reward_id.program_id")
order.program_ids |= programs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models

from odoo.addons.base.models.res_partner import Partner as ResPartner
from odoo.addons.sale.models.sale_order import SaleOrder
from odoo.addons.shopinvader_api_cart.schemas import CartTransaction

from ..schemas import LoyaltyRewardInput


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

@api.model
def _sync_cart(
self,
partner: ResPartner,
cart: SaleOrder,
uuid: str,
transactions: list[CartTransaction],
):
# TODO: will fail when several rewards are available
# TODO: was a skip_coupon_recompute in params...
cart = super()._sync_cart(partner, cart, uuid, transactions)
data = LoyaltyRewardInput()
self.env["shopinvader_api_loyalty.service.helper"]._recompute_coupon_lines(
cart, data
)
return cart
7 changes: 7 additions & 0 deletions shopinvader_api_sale_loyalty/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* `Camptocamp <https://www.camptocamp.com>`_

* Iván Todorovich <[email protected]>

* `Acsone <https://www.acsone.eu>`_

* Marie Lejeune <[email protected]>
7 changes: 7 additions & 0 deletions shopinvader_api_sale_loyalty/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
This module extends the functionality of Shopinvader to support Coupons
and Promotions from `sale_loyalty` core module.
It is the new version providing FastAPI services.

Not to be confused with `shopinvader_promotion_rule`, that implements
promotion programs from OCA module `sale_promotion_rule`, an alternative
to the core `sale_loyalty` module.
18 changes: 18 additions & 0 deletions shopinvader_api_sale_loyalty/readme/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
**Version 16:**

* A given code can now offer several rewards, and one can choose in each reward among several free products.
Hence the `apply_coupon` service had to be adapted to allow specifying reward and/or free product to apply.
It will raise an error if not enough info is specified.
* Due to the previous point the data structure had to be slightly modified:

- Several promo codes can be applied on a single SO. They are now exposed in `promo_codes`, a string which is a list of all promo codes.

- Several programs with code can be applied on a single SO.
It makes no more sense to distinguish automatic and with code programs. All of them
are stored in the same field `program_ids`.

- Program and rewards structure changed in customer's coupons data structure.
* Coupons are not restricted to their assigned partner anymore. What's more,
coupons that are generated from sale orders are not assigned to the related customer anymore.
See https://github.com/odoo/odoo/commit/6927dcda9f99db2a4d2f06b32f8d377c17fe2794 for more info.
It means that it is not possible to retrieve generated coupons from the customer `get` service.
1 change: 1 addition & 0 deletions shopinvader_api_sale_loyalty/routers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .loyalty import loyalty_router
Loading

0 comments on commit 3c6d596

Please sign in to comment.