Skip to content

Commit

Permalink
[WIP][MIG] shopinvader_api_delivery_carrier: Migration to 16.0 (FastAPI)
Browse files Browse the repository at this point in the history
  • Loading branch information
marielejeune committed Nov 29, 2023
1 parent b873c7a commit 64ca2d4
Show file tree
Hide file tree
Showing 79 changed files with 2,141 additions and 1,622 deletions.
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ exclude: |
^shopinvader_customer_price/|
^shopinvader_customer_price_wishlist/|
^shopinvader_customer_validate/|
^shopinvader_delivery_carrier/|
^shopinvader_delivery_instruction/|
^shopinvader_delivery_state/|
^shopinvader_demo_app/|
Expand Down
6 changes: 6 additions & 0 deletions setup/shopinvader_api_delivery_carrier/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,
)
6 changes: 6 additions & 0 deletions setup/shopinvader_delivery_carrier/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,
)
76 changes: 76 additions & 0 deletions shopinvader_api_delivery_carrier/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
===================
Shopinvader Carrier
===================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:fc9628b11d329cf0ae577a282d91760488fedda7d91f53ab53fc0ab8effa326d
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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_delivery_carrier
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

Add the configuration and the logic to manage the carrier on your ShopInvader site

**Table of contents**

.. contents::
:local:

Usage
=====

This module will give you several endpoints for interacting with delivery carrier.
You can play with it with swagger.

* Add a `/set_carrier` route on the `cart_router`: to set a delivery carrier on your cart;
* Create a new `delivery_carrier`: the route `delivery_carriers` allow to search on delivery carriers. You can filter on a specific cart, or on a specific country and/or zipcode.

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 to smash it by providing a detailed and welcomed
`feedback <https://github.com/shopinvader/odoo-shopinvader/issues/new?body=module:%20shopinvader_api_delivery_carrier%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
~~~~~~~

* Akretion
* Acsone

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

* Sebastien BEAU <[email protected]>
* Benoit GUILLOT <[email protected]>
* Laurent MIGNON <[email protected]>
* Cédric PIGEON <[email protected]>
* Denis ROUSSEL <[email protected]>
* Simone Orsi <[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_delivery_carrier>`_ project on GitHub.

You are welcome to contribute.
3 changes: 3 additions & 0 deletions shopinvader_api_delivery_carrier/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import services
from . import models
from . import routers
63 changes: 63 additions & 0 deletions shopinvader_api_delivery_carrier/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2017 Akretion (http://www.akretion.com)
# Sébastien BEAU <[email protected]>
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
"name": "Shopinvader Carrier",
"summary": "Carrier integration for Shopinvader",
"version": "16.0.1.0.0",
"category": "e-commerce",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"author": "Akretion, Acsone",
"license": "AGPL-3",
"application": True,
"installable": True,
"external_dependencies": {
"python": [
"fastapi",
"pydantic>=2.0.0",
"extendable-pydantic>=1.2.0",
],
},
"depends": [
"delivery",
# OCA/delivery-carrier
"delivery_carrier_info",
# OCA/queue
"queue_job",
# OCA/sale-workflow
"sale_shipping_info_helper",
"sale_discount_display_amount",
# Shopinvader
"pydantic",
"extendable",
"fastapi",
"extendable_fastapi",
"shopinvader_api_cart",
"shopinvader_api_security_sale",
"shopinvader_delivery_carrier",
"shopinvader_filtered_model",
"shopinvader_sale_cart",
"shopinvader_schema_sale",
],
"data": [
"security/groups.xml",
"security/acl_delivery_carrier.xml",
"security/acl_choose_delivery_carrier.xml",
"security/acl_product_pricelist_item.xml",
"security/acl_product_pricelist.xml",
"security/acl_product_category.xml",
"security/acl_account_tax.xml",
"security/acl_sale_order.xml",
"security/acl_sale_order_line.xml",
"security/acl_product_template.xml",
"security/acl_product_product.xml",
"security/acl_stock_picking.xml",
"security/acl_stock_picking_type.xml",
],
"demo": [
# "demo/mail_template.xml",
# "demo/shopinvader_notification.xml",
],
}
4 changes: 4 additions & 0 deletions shopinvader_api_delivery_carrier/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# from . import backend
# from . import shopinvader_notification
# from . import stock_picking
# from . import shopinvader_backend
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ShopinvaderBackend(models.Model):

_inherit = "shopinvader.backend"

# TODO: what to do with it?
delivery_order_states = fields.Selection(
string="Visible delivery order states",
selection=[
Expand Down
7 changes: 7 additions & 0 deletions shopinvader_api_delivery_carrier/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* Sebastien BEAU <[email protected]>
* Benoit GUILLOT <[email protected]>
* Laurent MIGNON <[email protected]>
* Cédric PIGEON <[email protected]>
* Denis ROUSSEL <[email protected]>
* Simone Orsi <[email protected]>
* Marie Lejeune <[email protected]>
1 change: 1 addition & 0 deletions shopinvader_api_delivery_carrier/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add the configuration and the logic to manage the carrier on your ShopInvader site
5 changes: 5 additions & 0 deletions shopinvader_api_delivery_carrier/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This module will give you several endpoints for interacting with delivery carrier.
You can play with it with swagger.

* Add a `/set_carrier` route on the `cart_router`: to set a delivery carrier on your cart;
* Create a new `delivery_carrier`: the route `delivery_carriers` allow to search on delivery carriers. You can filter on a specific cart, or on a specific country and/or zipcode.
3 changes: 3 additions & 0 deletions shopinvader_api_delivery_carrier/routers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import cart
from .delivery import delivery_router
from .delivery_carrier import delivery_carrier_router
78 changes: 78 additions & 0 deletions shopinvader_api_delivery_carrier/routers/cart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <[email protected]>
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from typing import Annotated

from fastapi import Depends

from odoo import _, api, models
from odoo.exceptions import UserError

from odoo.addons.base.models.res_partner import Partner as ResPartner
from odoo.addons.fastapi.dependencies import (
authenticated_partner,
authenticated_partner_env,
)
from odoo.addons.sale.models.sale_order import SaleOrder
from odoo.addons.shopinvader_api_cart.routers import cart_router
from odoo.addons.shopinvader_api_cart.schemas import CartTransaction
from odoo.addons.shopinvader_schema_sale.schemas import Sale

from ..schemas import DeliveryCarrierInput


@cart_router.post("/set_carrier")
@cart_router.post("/set_carrier/{uuid}")
def set_carrier(
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated["ResPartner", Depends(authenticated_partner)],
data: DeliveryCarrierInput,
uuid: str | None = None,
) -> Sale | None:
"""
If cart is found, set the carrier on it.
"""
cart = env["sale.order"]._find_open_cart(partner.id, uuid)
if not cart:
raise UserError(_("There is no cart"))
env["shopinvader_api_cart.cart_router.helper"]._set_carrier(cart, data)
return Sale.from_sale_order(cart) if cart else None


class ShopinvaderApiCartRouterHelper(models.AbstractModel):
_inherit = "shopinvader_api_cart.cart_router.helper"

# Set carrier
@api.model
def _set_carrier_and_price(self, cart, carrier_id):
ctx = self.env.context.copy()
ctx.update({"default_order_id": cart.id, "default_carrier_id": carrier_id})
wizard = self.env["choose.delivery.carrier"].with_context(**ctx).create({})
wizard._onchange_carrier_id()
wizard.button_confirm()
return wizard.delivery_price

@api.model
def _set_carrier(self, cart, data):
"""
Check if the carrier is available and set it on the cart.
"""
carrier_id = data.carrier_id
if carrier_id not in cart.shopinvader_available_carrier_ids.ids:
raise UserError(_("This delivery method is not available for your order"))
self._set_carrier_and_price(cart, carrier_id)

# Improve cart synchronization: remove carrier everytime an item is updated
@api.model
def _sync_cart(
self,
partner: ResPartner,
cart: SaleOrder,
uuid: str,
transactions: list[CartTransaction],
):
cart = super()._sync_cart(partner, cart, uuid, transactions)
if transactions:
cart._remove_delivery_line()
return cart
70 changes: 70 additions & 0 deletions shopinvader_api_delivery_carrier/routers/delivery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from typing import Annotated

from fastapi import APIRouter, Depends

from odoo import api, fields, models

from odoo.addons.base.models.res_partner import Partner as ResPartner
from odoo.addons.extendable_fastapi.schemas import PagedCollection
from odoo.addons.fastapi.dependencies import (
authenticated_partner,
authenticated_partner_env,
paging,
)
from odoo.addons.fastapi.schemas import Paging
from odoo.addons.shopinvader_filtered_model.utils import FilteredModelAdapter
from odoo.addons.stock.models.stock_picking import Picking as StockPicking

from ..schemas import Picking

delivery_router = APIRouter(tags=["deliveries"])


@delivery_router.get("/deliveries")
def search(
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated["ResPartner", Depends(authenticated_partner)],
paging_: Annotated[Paging, Depends(paging)],
) -> PagedCollection[Picking]:
count, pickings = (
env["shopinvader_api_delivery_carrier.delivery_router.helper"]
.new({"partner": partner})
._search(paging_)
)
return PagedCollection[Picking](
count=count, items=[Picking.from_picking(picking) for picking in pickings]
)


class ShopinvaderApiDeliveryRouterHelper(models.AbstractModel):
_name = "shopinvader_api_delivery_carrier.delivery_router.helper"
_description = "ShopInvader API Delivery Router Helper"

partner = fields.Many2one("res.partner")

def _get_domain_adapter(self):
sales = self.env["sale.order"].search(
[("typology", "=", "sale"), ("partner_id", "=", self.partner.id)]
)
# TODO: here and on the sale schema, we filtered on the allowed states
# on the shopinvader.backend
return [
("sale_id", "in", sales.ids),
("picking_type_id.code", "=", "outgoing"),
]

@property
def model_adapter(self) -> FilteredModelAdapter[StockPicking]:
return FilteredModelAdapter[StockPicking](self.env, self._get_domain_adapter())

def _get(self, record_id) -> StockPicking:
return self.model_adapter.get(record_id)

def _search(self, paging) -> tuple[int, StockPicking]:
return self.model_adapter.search_with_count(
[],
limit=paging.limit,
offset=paging.offset,
)
Loading

0 comments on commit 64ca2d4

Please sign in to comment.