Skip to content

Commit 9073abf

Browse files
[16.0][MIG] shopinvader_delivery_pickup: Migration to 16.0 (FastAPI)
1 parent 2f9264a commit 9073abf

36 files changed

+1038
-416
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# addons listed in this file are ignored by
2+
# setuptools-odoo-make-default (one addon per line)

setup/README

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
To learn more about this directory, please visit
2+
https://pypi.python.org/pypi/setuptools-odoo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../shopinvader_api_delivery_pickup
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import setuptools
2+
3+
setuptools.setup(
4+
setup_requires=['setuptools-odoo'],
5+
odoo_addon=True,
6+
)
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
===========================
2+
Shopinvader Delivery Pickup
3+
===========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:d1c0d9ae60c51081ab91a8e029129c55cea1cc48162865c0fa7ae2bee91e9c05
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-shopinvader%2Fodoo--shopinvader--carrier-lightgray.png?logo=github
20+
:target: https://github.com/shopinvader/odoo-shopinvader-carrier/tree/16.0/shopinvader_api_delivery_pickup
21+
:alt: shopinvader/odoo-shopinvader-carrier
22+
23+
|badge1| |badge2| |badge3|
24+
25+
Expose pickup sites to shopinvader API
26+
27+
**Table of contents**
28+
29+
.. contents::
30+
:local:
31+
32+
Known issues / Roadmap
33+
======================
34+
35+
For now the module only implement a fastapi for setting the dropoffsite.
36+
37+
TODO:
38+
- add the possibility to search a dropoff_site with geo location
39+
40+
Bug Tracker
41+
===========
42+
43+
Bugs are tracked on `GitHub Issues <https://github.com/shopinvader/odoo-shopinvader-carrier/issues>`_.
44+
In case of trouble, please check there if your issue has already been reported.
45+
If you spotted it first, help us to smash it by providing a detailed and welcomed
46+
`feedback <https://github.com/shopinvader/odoo-shopinvader-carrier/issues/new?body=module:%20shopinvader_api_delivery_pickup%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
47+
48+
Do not contact contributors directly about support or help with technical issues.
49+
50+
Credits
51+
=======
52+
53+
Authors
54+
~~~~~~~
55+
56+
* Akretion
57+
* ACSONE SA/NV
58+
* Shopinvader
59+
60+
Contributors
61+
~~~~~~~~~~~~
62+
63+
* Sebastien BEAU <[email protected]>
64+
* Laurent Mignon <[email protected]>
65+
* Raphaël Reverdy <[email protected]>
66+
* Chafique DELLI <[email protected]>
67+
68+
Other credits
69+
~~~~~~~~~~~~~
70+
71+
The development of this module has been financially supported by:
72+
73+
* Akretion
74+
* ACSONE SA/NV
75+
76+
Maintainers
77+
~~~~~~~~~~~
78+
79+
This module is part of the `shopinvader/odoo-shopinvader-carrier <https://github.com/shopinvader/odoo-shopinvader-carrier/tree/16.0/shopinvader_api_delivery_pickup>`_ project on GitHub.
80+
81+
You are welcome to contribute.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import routers
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
# Copyright 2019 Akretion (http://www.akretion.com)
1+
# Copyright 2019-2024 Akretion (http://www.akretion.com)
22
# Sébastien BEAU <[email protected]>
33
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
44

55
{
6-
"name": "Shopinvader Delivery pickup",
6+
"name": "Shopinvader Delivery Pickup",
77
"summary": "Allows to deliver sale order to pickup site",
8-
"version": "12.0.1.0.0",
8+
"version": "16.0.1.0.0",
99
"category": "e-commerce",
1010
"website": "https://github.com/shopinvader/odoo-shopinvader-carrier",
11-
"author": "Akretion, ACSONE SA/NV",
11+
"author": "Akretion, ACSONE SA/NV, Shopinvader",
1212
"license": "AGPL-3",
1313
"application": False,
1414
"installable": True,
1515
"external_dependencies": {"python": [], "bin": []},
16-
"depends": ["shopinvader_delivery_carrier", "delivery_dropoff_site"],
17-
"data": [],
16+
"depends": ["shopinvader_api_delivery_carrier", "delivery_dropoff_site"],
17+
"data": [
18+
"security/groups.xml",
19+
"security/acl_delivery_pickup.xml",
20+
],
1821
"demo": [],
1922
"qweb": [],
2023
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
* Sebastien BEAU <[email protected]>
22
* Laurent Mignon <[email protected]>
33
* Raphaël Reverdy <[email protected]>
4+
* Chafique DELLI <[email protected]>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
For now the module only implement a fastapi for setting the dropoffsite.
2+
3+
TODO:
4+
- add the possibility to search a dropoff_site with geo location
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import cart
2+
from .delivery_pickup import delivery_pickup_router
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright 2019 Akretion (http://www.akretion.com).
2+
# @author Sébastien BEAU <[email protected]>
3+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
4+
from typing import Annotated
5+
6+
from fastapi import Depends
7+
8+
from odoo import _, api, models
9+
from odoo.exceptions import UserError
10+
11+
from odoo.addons.base.models.res_partner import Partner as ResPartner
12+
from odoo.addons.fastapi.dependencies import (
13+
authenticated_partner,
14+
authenticated_partner_env,
15+
)
16+
from odoo.addons.sale.models.sale_order import SaleOrder
17+
from odoo.addons.shopinvader_api_cart.routers import cart_router
18+
from odoo.addons.shopinvader_api_cart.schemas import CartTransaction
19+
from odoo.addons.shopinvader_schema_sale.schemas import Sale
20+
21+
from ..schemas import DeliveryPickupInput
22+
23+
24+
@cart_router.post("/set_pickup")
25+
@cart_router.post("/{uuid}/set_pickup")
26+
@cart_router.post("/current/set_pickup")
27+
def set_delivery_pickup(
28+
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
29+
partner: Annotated["ResPartner", Depends(authenticated_partner)],
30+
data: DeliveryPickupInput,
31+
uuid: str | None = None,
32+
) -> Sale | None:
33+
"""
34+
If cart is found, set the pickup site on it.
35+
"""
36+
cart = env["sale.order"]._find_open_cart(partner.id, uuid)
37+
if not cart:
38+
raise UserError(_("There is no cart"))
39+
env["shopinvader_api_cart.cart_router.helper"]._set_delivery_pickup(cart, data)
40+
return Sale.from_sale_order(cart) if cart else None
41+
42+
43+
class ShopinvaderApiCartRouterHelper(models.AbstractModel):
44+
_inherit = "shopinvader_api_cart.cart_router.helper"
45+
46+
# Set delivery pickup
47+
@api.model
48+
def _set_delivery_pickup(self, cart, data):
49+
pickup_site = self.env["dropoff.site"].search(
50+
[("id", "=", data.pickup_site_id)]
51+
)
52+
if not pickup_site:
53+
raise UserError(_("Invalid code for pickup site"))
54+
if pickup_site.carrier_id not in cart.shopinvader_available_carrier_ids:
55+
raise UserError(_("This delivery method is not available for your order"))
56+
self._set_carrier_and_price(cart, pickup_site.carrier_id.id)
57+
vals = {"partner_shipping_id": pickup_site.partner_id.id}
58+
if not cart.final_shipping_partner_id:
59+
vals["final_shipping_partner_id"] = cart.partner_shipping_id.id
60+
cart.sudo().write(vals)
61+
62+
@api.model
63+
def _reset_delivery_pickup(self, cart):
64+
if cart.final_shipping_partner_id:
65+
cart.partner_shipping_id = cart.final_shipping_partner_id
66+
cart.final_shipping_partner_id = None
67+
68+
@api.model
69+
def _set_carrier(self, cart, data):
70+
self._reset_delivery_pickup(cart)
71+
return super()._set_carrier(cart, data)
72+
73+
@api.model
74+
def _sync_cart(
75+
self,
76+
partner: ResPartner,
77+
cart: SaleOrder,
78+
uuid: str,
79+
transactions: list[CartTransaction],
80+
):
81+
cart = super()._sync_cart(partner, cart, uuid, transactions)
82+
if transactions:
83+
self._reset_delivery_pickup(cart)
84+
return cart
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2019 ACSONE SA/NV
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from typing import Annotated
4+
5+
from fastapi import APIRouter, Depends
6+
7+
from odoo import api, models
8+
from odoo.osv import expression
9+
10+
from odoo.addons.base.models.res_partner import Partner as ResPartner
11+
from odoo.addons.delivery_dropoff_site.models.dropoff_site import DropoffSite
12+
from odoo.addons.fastapi.dependencies import (
13+
authenticated_partner,
14+
authenticated_partner_env,
15+
)
16+
17+
from ..schemas import DeliveryPickup as DeliveryPickupSchema, DeliveryPickupSearch
18+
19+
delivery_pickup_router = APIRouter(tags=["delivery_pickups"])
20+
21+
22+
@delivery_pickup_router.get("/delivery_pickups")
23+
def search(
24+
data: Annotated[DeliveryPickupSearch, Depends()],
25+
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
26+
partner: Annotated[ResPartner, Depends(authenticated_partner)],
27+
) -> list[DeliveryPickupSchema]:
28+
"""
29+
Returns the list of all available pickup sites.
30+
31+
If cart, the list will be limited to the
32+
pickup sites linked to carriers applying to the current cart.
33+
34+
If you don't provide a carrier_id, the service will return all the
35+
pickup sites linked to carriers available for this site.
36+
37+
If you provide a carrier_id, only the pickup sites linked to the given
38+
carrier are returned except if the carrier is not available for this
39+
site.
40+
"""
41+
delivery_pickups = (
42+
env["shopinvader_api_delivery_pickup.delivery_pickup_router.helper"]
43+
.new({"partner": partner})
44+
._search(data, cart=None)
45+
)
46+
return [
47+
DeliveryPickupSchema.from_delivery_pickup(delivery_pickup)
48+
for delivery_pickup in delivery_pickups
49+
]
50+
51+
52+
class ShopinvaderApiDeliveryRouterHelper(models.AbstractModel):
53+
_name = "shopinvader_api_delivery_pickup.delivery_pickup_router.helper"
54+
_description = "ShopInvader API Delivery Pickup Router Helper"
55+
56+
def _search(self, data, cart=None) -> DropoffSite:
57+
"""
58+
Search for delivery pickup sites
59+
:return: a list of dropoff.site
60+
"""
61+
cart.ensure_one()
62+
domain = data.to_odoo_domain()
63+
if cart:
64+
domain = expression.AND(
65+
domain,
66+
[("carrier_id", "in", cart.shopinvader_available_carrier_ids.ids)],
67+
)
68+
return self.env["dropoff.site"].search(domain)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from .resource_calendar_attendance import ResourceCalendarAttendance
2+
from .delivery_pickup import (
3+
DeliveryPickup,
4+
DeliveryPickupInput,
5+
DeliveryPickupSearch,
6+
)
7+
from .address import DeliveryAddress
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright 2019 ACSONE SA/NV
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo.addons.shopinvader_schema_address import schemas
5+
6+
7+
class DeliveryAddress(schemas.DeliveryAddress, extends=True):
8+
is_dropoff_site: bool | None = None
9+
10+
@classmethod
11+
def from_res_partner(cls, odoo_rec):
12+
res = super().from_res_partner(odoo_rec)
13+
res.is_dropoff_site = odoo_rec.is_dropoff_site or None
14+
return res
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright 2019 ACSONE SA/NV
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from typing import Annotated, Field, List
4+
5+
from extendable_pydantic import StrictExtendableBaseModel
6+
7+
from odoo import api
8+
9+
from ..schemas import ResourceCalendarAttendance
10+
11+
12+
class DeliveryPickupInput(StrictExtendableBaseModel):
13+
pickup_site_id: int
14+
15+
16+
class DeliveryPickupSearch(StrictExtendableBaseModel):
17+
name: Annotated[
18+
str | None,
19+
Field(
20+
description="When used, the search look for any delivery pickup where name "
21+
"contains the given value case insensitively."
22+
),
23+
] = None
24+
carrier_id: Annotated[
25+
int | None,
26+
Field(
27+
description="When used, the search look for any delivery pickup where carrier "
28+
"contains the given value case insensitively."
29+
),
30+
] = None
31+
32+
def to_odoo_domain(self, env: api.Environment):
33+
domain = []
34+
if self.name:
35+
domain.append(("name", "ilike", self.name))
36+
if self.carrier_id:
37+
domain.append(("carrier_id", "ilike", self.carrier_id.id))
38+
return domain
39+
40+
41+
class DeliveryPickup(StrictExtendableBaseModel):
42+
id: int
43+
name: str
44+
code: str | None = None
45+
partner_id: int
46+
street: str | None = None
47+
street2: str | None = None
48+
zip: str | None = None
49+
city: str | None = None
50+
phone: str | None = None
51+
state_id: int | None = None
52+
country_id: int
53+
carrier_id: int
54+
calendar_id: int | None = None
55+
attendance_ids: List[ResourceCalendarAttendance] | None = None
56+
57+
@classmethod
58+
def from_delivery_pickup(cls, odoo_rec):
59+
return cls.model_construct(
60+
id=odoo_rec.id,
61+
name=odoo_rec.name,
62+
code=odoo_rec.code or None,
63+
partner_id=odoo_rec.partner_id.id,
64+
street=odoo_rec.street or None,
65+
street2=odoo_rec.street2 or None,
66+
zip=odoo_rec.zip or None,
67+
city=odoo_rec.city or None,
68+
phone=odoo_rec.phone or None,
69+
state_id=odoo_rec.state_id.id or None,
70+
country_id=odoo_rec.country_id.id,
71+
carrier_id=odoo_rec.carrier_id.id,
72+
calendar_id=odoo_rec.calendar_id.id or None,
73+
attendance_ids=[
74+
ResourceCalendarAttendance.from_resource_calendar_attendance(attendance)
75+
for attendance in odoo_rec.attendance_ids
76+
]
77+
or None,
78+
)

0 commit comments

Comments
 (0)