Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][MIG] shopinvader_lead: Migration to 16.0 #1405

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# generated from manifests external_dependencies
extendable-pydantic>=1.0.0
extendable-pydantic>=1.1.0
extendable_pydantic>=1.0.0
extendable_pydantic>=1.1.0
Expand Down
6 changes: 6 additions & 0 deletions setup/shopinvader_api_lead/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,
)
64 changes: 64 additions & 0 deletions shopinvader_api_lead/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
================
Shopinvader Lead
================

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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/14.0/shopinvader_lead
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

Allows to create leads from your website, in a 'contact us' form for example.

**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 smashing it by providing a detailed and welcomed
`feedback <https://github.com/shopinvader/odoo-shopinvader/issues/new?body=module:%20shopinvader_lead%0Aversion:%2014.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 <sebastien.beau@akretion.com>
* Pierrick Brun <pierrick.brun@akretion.com>

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

* Akretion R&D
* Adaptoo

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

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

You are welcome to contribute.
2 changes: 2 additions & 0 deletions shopinvader_api_lead/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import routers
from . import schemas
18 changes: 18 additions & 0 deletions shopinvader_api_lead/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Shopinvader Api Lead",
"summary": "Shopinvader Lead Management",
"version": "16.0.1.0.1",
"category": "e-commerce",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"author": "Akretion",
"license": "AGPL-3",
"depends": ["crm", "fastapi"],
"external_dependencies": {
"python": [
"fastapi",
"pydantic>=2.0.0",
"extendable-pydantic>=1.0.0",
]
},
"installable": True,
}
1 change: 1 addition & 0 deletions shopinvader_api_lead/readme/CONFIGURATION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Create a form on your website with the controller "lead"
2 changes: 2 additions & 0 deletions shopinvader_api_lead/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Sebastien BEAU <sebastien.beau@akretion.com>
* Pierrick Brun <pierrick.brun@akretion.com>
2 changes: 2 additions & 0 deletions shopinvader_api_lead/readme/CREDITS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Akretion R&D
* Adaptoo
1 change: 1 addition & 0 deletions shopinvader_api_lead/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allows to create leads from your website, in a 'contact us' form for example.
1 change: 1 addition & 0 deletions shopinvader_api_lead/routers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import lead
22 changes: 22 additions & 0 deletions shopinvader_api_lead/routers/lead.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Annotated

from fastapi import APIRouter, Depends

from odoo.api import Environment

from odoo.addons.base.models.res_partner import Partner as ResPartner
from odoo.addons.fastapi.dependencies import authenticated_partner, odoo_env

from ..schemas import LeadService

# create a router
leads_router = APIRouter()


@leads_router.post("/leads", status_code=201)
def post_leads(
data: LeadService,
env: Annotated[Environment, Depends(odoo_env)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
) -> None:
env["crm.lead"].create(data.to_crm_lead_vals(partner))
48 changes: 48 additions & 0 deletions shopinvader_api_lead/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from pydantic import BaseModel


class LeadService(BaseModel):
email: str | None = None
name: str | None = None
description: str | None = None
company: str | None = None
street: str | None = None
street2: str | None = None
zip: str | None = None
city: str | None = None
phone: str | None = None
mobile: str | None = None
state_id: int | None = None
country_id: int | None = None
team_id: int | None = None
contact_name: str | None = None

# # faire un module supp pour ces champs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO add a module: shopinvader_api_lead_firstname

# if "crm_lead_firstname" in odoo_env().registry._init_modules:
# contact_firstname: str
# # contact_name: str = pydantic.Field(alias="contact_firstname") | None
# contact_lastname: str
# else:
# contact_name: str

def to_crm_lead_vals(self, partner=None) -> dict:
vals = {
"email_from": self.email,
"name": self.name,
"description": self.description,
"partner_name": self.company,
"street": self.street,
"street2": self.street2,
"zip": self.zip,
"city": self.city,
"phone": self.phone,
"mobile": self.mobile,
"state_id": self.state_id,
"country_id": self.country_id,
"team_id": self.team_id,
"contact_name": self.contact_name,
}
if partner:
vals.pop("email_from", None)
vals["partner_id"] = partner.id
return vals
1 change: 1 addition & 0 deletions shopinvader_api_lead/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_shopinvader_lead
92 changes: 92 additions & 0 deletions shopinvader_api_lead/tests/test_shopinvader_lead.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright 2023 Akretion (https://www.akretion.com).
# @author Matthieu SAISON <matthieu.saison@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import json

from fastapi import status
from requests import Response

from odoo import models
from odoo.tests.common import tagged

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

from ..routers.lead import leads_router


@tagged("post_install", "-at_install")
class TestShopinvaderLeadsApi(FastAPITransactionCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()

cls.test_partner = cls.env["res.partner"].create(
{
"name": "osiris",
"street": "rue test",
"zip": "1410",
"city": "Waterloo",
"country_id": cls.env.ref("base.be").id,
"email": "osiris@shopinvader.com",
}
)
cls.default_fastapi_authenticated_partner = cls.env["res.partner"]
cls.default_fastapi_router = leads_router

def test_create_lead(self):
data = {
"email": "revolution@shopinvader.com",
"name": "Besoin d'un nouveau site",
"company": "Adaptoo",
"street": "1 Rue Henri Matisse",
"zip": "84310",
"city": "MORIERES-LES-AVIGNON",
"contact_name": "La famille",
"description": "<p>Help, on ne supporte plus magento</p>",
"country_id": self.env.ref("base.fr").id,
"mobile": "0600000000",
}
check_data = data.copy()
check_data.update(
{
"partner_name": check_data.pop("company"),
"email_from": check_data.pop("email"),
}
)
with self._create_test_client() as test_client:
response: Response = test_client.post("/leads", content=json.dumps(data))
self.assertEqual(
response.status_code,
status.HTTP_201_CREATED,
msg=f"error message: {response.text}",
)

lead = self.env["crm.lead"].search([], order="id desc", limit=1)[0]
for key in check_data:
if isinstance(lead[key], models.Model):
self.assertEqual(lead[key].id, check_data[key])
else:
self.assertEqual(lead[key], check_data[key])
# TODO split shopinvader tests.test_notification
# self._check_notification("lead_confirmation", lead)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO to discuss


def test_create_lead_with_logged_partner(self):

data = {
"name": "Besoin d'un nouveau site",
"description": "Help, on ne supporte plus magento",
"email": "bliblablo@example.org",
}
with self._create_test_client(partner=self.test_partner) as test_client:
response: Response = test_client.post("/leads", content=json.dumps(data))
self.assertEqual(
response.status_code,
status.HTTP_201_CREATED,
msg=f"error message: {response.text}",
)

lead = self.env["crm.lead"].search([], order="id desc", limit=1)
self.assertEqual(lead.name, "Besoin d'un nouveau site")
self.assertEqual(lead.partner_id.email, "osiris@shopinvader.com")
self.assertEqual(lead.partner_id, self.test_partner)
Loading