Skip to content

Commit

Permalink
[IMP] shopinvader_api_sale: Add sale_line router
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Mar 5, 2024
1 parent f833d61 commit e1c2907
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 1 deletion.
1 change: 1 addition & 0 deletions shopinvader_api_sale/routers/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .sales import sale_router
from .sale_lines import sale_line_router
86 changes: 86 additions & 0 deletions shopinvader_api_sale/routers/sale_lines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# 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.sale.models.sale_order_line import SaleOrderLine
from odoo.addons.shopinvader_filtered_model.utils import FilteredModelAdapter

from ..schemas import SaleLineSearch, SaleLineWithSale

sale_line_router = APIRouter(tags=["sales"])


@sale_line_router.get("/sale_lines")
def search(
params: Annotated[SaleLineSearch, Depends()],
paging: Annotated[Paging, Depends(paging)],
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
) -> PagedCollection[SaleLineWithSale]:
"""Get / search sale order lines. The list contains only sale order lines from the
authenticated user"""
count, sols = (
env["shopinvader_api_sale.sale_line_router.helper"]
.new({"partner": partner})
._search(paging, params)
)
return PagedCollection[SaleLineWithSale](
count=count,
items=[SaleLineWithSale.from_sale_order_line(sol) for sol in sols],
)


@sale_line_router.get("/sale_lines/{sale_line_id}")
def get(
sale_line_id: int,
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
) -> SaleLineWithSale:
"""
Get sale order of authenticated user with specific sale_id
"""
return SaleLineWithSale.from_sale_order_line(
env["shopinvader_api_sale.sale_line_router.helper"]
.new({"partner": partner})
._get(sale_line_id)
)


class ShopinvaderApiSaleSaleLineRouterHelper(models.AbstractModel):
_name = "shopinvader_api_sale.sale_line_router.helper"
_description = "Shopinvader Api Sale Line Service Helper"

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

def _get_domain_adapter(self):
return [
("order_id.partner_id", "=", self.partner.id),
("order_id.typology", "=", "sale"),
]

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

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

def _search(self, paging, params) -> tuple[int, SaleOrderLine]:
return self.model_adapter.search_with_count(
params.to_odoo_domain(self.env),
limit=paging.limit,
offset=paging.offset,
)
48 changes: 48 additions & 0 deletions shopinvader_api_sale/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from typing import Annotated

from extendable_pydantic import StrictExtendableBaseModel
from pydantic import Field

from odoo import api

from odoo.addons.shopinvader_schema_sale.schemas.sale_line import SaleLine


class SaleLineWithSale(SaleLine):
order_id: int

@classmethod
def from_sale_order_line(cls, odoo_rec):
res = super().from_sale_order_line(odoo_rec)
res.order_id = odoo_rec.order_id.id
return res


class SaleLineSearch(StrictExtendableBaseModel, extra="ignore"):
order_name: Annotated[
str | None,
Field(
description="When used, the search look for any sale order lines "
"where the order name contains the given value case insensitively."
),
] = None
product_name: Annotated[
str | None,
Field(
description="When used, the search look for any sale order lines "
"where the product name contains the given value case insensitively."
),
] = None

def to_odoo_domain(self, env: api.Environment):
domain = []
if self.order_name:
domain.append(("order_id.name", "ilike", self.order_name))

if self.product_name:
domain.append(("product_id.name", "ilike", self.product_name))

return domain
32 changes: 31 additions & 1 deletion shopinvader_api_sale/tests/test_shopinvader_sale_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from odoo.addons.extendable_fastapi.tests.common import FastAPITransactionCase

from ..routers import sale_router
from ..routers import sale_line_router, sale_router


@tagged("post_install", "-at_install")
Expand Down Expand Up @@ -94,3 +94,33 @@ def test_download(self):
response: Response = test_client.get(f"/sales/{sale.id}/download")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.headers["Content-Type"], "application/pdf")

def test_search_sale_lines(self):
so1 = self.env["sale.order"].create(
{"partner_id": self.default_fastapi_authenticated_partner.id}
)
so1.write(
{
"order_line": [
(0, 0, {"product_id": self.product_1.id, "product_uom_qty": 2}),
(0, 0, {"product_id": self.product_2.id, "product_uom_qty": 6}),
]
}
)
so2 = self.env["sale.order"].create(
{"partner_id": self.default_fastapi_authenticated_partner.id}
)
so2.write(
{
"order_line": [
(0, 0, {"product_id": self.product_1.id, "product_uom_qty": 1}),
(0, 0, {"product_id": self.product_2.id, "product_uom_qty": 3}),
(0, 0, {"product_id": self.product_1.id, "product_uom_qty": 4}),
]
}
)

with self._create_test_client(router=sale_line_router) as test_client:
response: Response = test_client.get("/sale_lines")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["count"], 5)

0 comments on commit e1c2907

Please sign in to comment.