Skip to content

Commit

Permalink
migrate shopinvader quotation to fastapi
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieu.saison committed Jan 18, 2024
1 parent ff8c56f commit 2fead05
Show file tree
Hide file tree
Showing 16 changed files with 873 additions and 0 deletions.
6 changes: 6 additions & 0 deletions setup/shopinvader_api_quotation/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,
)
82 changes: 82 additions & 0 deletions shopinvader_api_quotation/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
=========================
Shopinvader Api Quotation
=========================

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

|badge1| |badge2| |badge3|

This module adds a REST API for shopinvader to manage quotations.

The Customer can convert a cart into a quotation (the typology of the sale
order is set to quotation).

Initially, the quotation has the `shopinvader_state` "estimating".
After updating the price manually when the button "sent" on Odoo backend
is submitted, the quotation will be sent by email (native behaviour) and the
shopinvader_state will switch to "estimated".

On Shopinvader site, the customer can see the state, the amount ... of quotation.

**Table of contents**

.. contents::
:local:

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_quotation%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

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

* Sebastien BEAU <[email protected]>
* Benoît GUILLOT <[email protected]>
* Iván Todorovich <[email protected]>
* Simone Orsi <[email protected]>
* Matthieu Saison <[email protected]>

Other credits
~~~~~~~~~~~~~

The development of this module has been financially supported by:

* Akretion R&D
* LaboAndCo

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

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

You are welcome to contribute.
1 change: 1 addition & 0 deletions shopinvader_api_quotation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import routers
28 changes: 28 additions & 0 deletions shopinvader_api_quotation/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "Shopinvader Api Quotation",
"summary": "Shopinvader Quotation",
"version": "16.0.1.0.1",
"category": "e-commerce",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"author": "Akretion",
"license": "AGPL-3",
"depends": [
"crm",
"fastapi",
"shopinvader_schema_sale",
"shopinvader_api_security_sale",
"shopinvader_api_cart",
"shopinvader_api_sale",
"sale_cart",
"sale_quotation",
],
"data": [],
"external_dependencies": {
"python": [
"fastapi",
"pydantic>=2.0.0",
"extendable_pydantic>=1.0.0",
]
},
"installable": True,
}
5 changes: 5 additions & 0 deletions shopinvader_api_quotation/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* Sebastien BEAU <[email protected]>
* Benoît GUILLOT <[email protected]>
* Iván Todorovich <[email protected]>
* Simone Orsi <[email protected]>
* Matthieu Saison <[email protected]>
4 changes: 4 additions & 0 deletions shopinvader_api_quotation/readme/CREDITS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The development of this module has been financially supported by:

* Akretion R&D
* LaboAndCo
11 changes: 11 additions & 0 deletions shopinvader_api_quotation/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
This module adds a REST API for shopinvader to manage quotations.

The Customer can convert a cart into a quotation (the typology of the sale
order is set to quotation).

Initially, the quotation has the `shopinvader_state` "estimating".
After updating the price manually when the button "sent" on Odoo backend
is submitted, the quotation will be sent by email (native behaviour) and the
shopinvader_state will switch to "estimated".

On Shopinvader site, the customer can see the state, the amount ... of quotation.
2 changes: 2 additions & 0 deletions shopinvader_api_quotation/routers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import quotation
from . import cart
34 changes: 34 additions & 0 deletions shopinvader_api_quotation/routers/cart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import Annotated

from fastapi import Depends

from odoo import api, models

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.shopinvader_api_cart.routers import cart_router
from odoo.addons.shopinvader_schema_sale.schemas.sale import Sale


@cart_router.post("/{uuid}/request_quotation")
def request_quotation(
env: Annotated[api.Environment, Depends(authenticated_partner_env)],
partner: Annotated["ResPartner", Depends(authenticated_partner)],
uuid: str | None = None,
) -> Sale:
sale = env["shopinvader_api_cart.cart_router.helper"]._request_quotation(
partner, uuid
)
return Sale.from_sale_order(sale)


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

def _request_quotation(self, partner, uuid):
sale = self.env["sale.order"]._find_open_cart(partner.id, uuid)
sale.action_request_quotation()
return sale
102 changes: 102 additions & 0 deletions shopinvader_api_quotation/routers/quotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from typing import Annotated

from fastapi import APIRouter, Depends

from odoo import models
from odoo.api import Environment

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_schema_sale.schemas.sale import Sale, SaleSearch

from ..schemas.sale import QuotationUpdateInput

# create a router
quotation_router = APIRouter(tags=["quotations"])


@quotation_router.get("/quotations/{quotation_id}")
def get(
env: Annotated[Environment, Depends(authenticated_partner_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
quotation_id: int,
) -> Sale | None:
return Sale.from_sale_order(
env["shopinvader_api_quotation.quotations_router.helper"]
.new({"partner": partner})
._get(quotation_id)
)


@quotation_router.post("/quotations/{quotation_id}/confirm", status_code=200)
def confirm_quotation(
env: Annotated[Environment, Depends(authenticated_partner_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
quotation_id: int,
) -> None:
order = (
env["shopinvader_api_quotation.quotations_router.helper"]
.new({"partner": partner})
._confirm(quotation_id)
)
return Sale.from_sale_order(order)


@quotation_router.get("/quotations", status_code=200)
def search_quotation(
params: Annotated[SaleSearch, Depends()],
paging: Annotated[Paging, Depends(paging)],
env: Annotated[Environment, Depends(authenticated_partner_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
) -> PagedCollection[Sale]:
count, orders = (
env["shopinvader_api_quotation.quotations_router.helper"]
.new({"partner": partner})
._search(paging, params)
)
return PagedCollection[Sale](
count=count,
items=[Sale.from_sale_order(order) for order in orders],
)


@quotation_router.post("/quotations/{quotation_id}")
def update_quotation(
data: QuotationUpdateInput,
env: Annotated[Environment, Depends(authenticated_partner_env)],
partner: Annotated["ResPartner", Depends(authenticated_partner)],
quotation_id: int,
) -> Sale:
order = (
env["shopinvader_api_quotation.quotations_router.helper"]
.new({"partner": partner})
._update(quotation_id, data)
)
return Sale.from_sale_order(order)


class ShopinvaderApiSaleSalesRouterHelper(models.AbstractModel):
_name = "shopinvader_api_quotation.quotations_router.helper"
_inherit = "shopinvader_api_sale.sales_router.helper"

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

def _confirm(self, quotation_id):
order = self._get(quotation_id)
order.action_confirm_quotation()
return order

def _update(self, quotation_id, data):
order = self._get(quotation_id)
order.write(data.to_sale_order_vals())
return order
1 change: 1 addition & 0 deletions shopinvader_api_quotation/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import sale
27 changes: 27 additions & 0 deletions shopinvader_api_quotation/schemas/sale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from extendable_pydantic import StrictExtendableBaseModel

from odoo.addons.shopinvader_schema_sale.schemas.sale import Sale


class Sale(Sale, extends=True):
available_for_quotation: bool | None = None
shop_only_quotation: bool | None = None
customer_ref: str | None = None

@classmethod
def from_sale_order(cls, odoo_rec):
res = super().from_sale_order(odoo_rec)
res.available_for_quotation = True
res.shop_only_quotation = odoo_rec.shop_only_quotation
res.customer_ref = odoo_rec.client_order_ref or None
# res.shop_only_quotation = any(
# odoo_rec.order_line.product_id.mapped("shop_only_quotation")
# ) mettre un champs calculé coté odoo sur model sale_order
return res


class QuotationUpdateInput(StrictExtendableBaseModel):
customer_ref: str | None = None

def to_sale_order_vals(self) -> dict:
return {"client_order_ref": self.customer_ref}
Loading

0 comments on commit 2fead05

Please sign in to comment.