Skip to content

Commit

Permalink
Merge PR #1521 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by simahawk
  • Loading branch information
shopinvader-git-bot committed May 6, 2024
2 parents 0f73c49 + 0f1dfd8 commit b3d27b5
Show file tree
Hide file tree
Showing 28 changed files with 423 additions and 0 deletions.
1 change: 1 addition & 0 deletions sale_cart_step/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bot pls :)
1 change: 1 addition & 0 deletions sale_cart_step/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
20 changes: 20 additions & 0 deletions sale_cart_step/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Sale Cart steps",
"summary": """
Track checkout steps on sale cart.
""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Camptocamp",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"depends": ["sale_cart"],
"data": [
"data/cart_step.xml",
"security/ir.model.access.csv",
"views/sale_order.xml",
"views/cart_step.xml",
],
}
19 changes: 19 additions & 0 deletions sale_cart_step/data/cart_step.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">

<record id="cart_step_address" model="sale.order.cart.step">
<field name="name">Address</field>
<field name="code">address</field>
</record>

<record id="cart_step_checkout" model="sale.order.cart.step">
<field name="name">Checkout</field>
<field name="code">checkout</field>
</record>

<record id="cart_step_last" model="sale.order.cart.step">
<field name="name">Last</field>
<field name="code">last</field>
</record>

</odoo>
2 changes: 2 additions & 0 deletions sale_cart_step/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import sale_order
from . import sale_order_cart_step
42 changes: 42 additions & 0 deletions sale_cart_step/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2024 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, exceptions, fields, models


class SaleOrder(models.Model):

_inherit = "sale.order"

cart_step_id = fields.Many2one(
comodel_name="sale.order.cart.step", string="Current cart step", readonly=True
)
cart_step_done_ids = fields.Many2many(
comodel_name="sale.order.cart.step",
string="Done cart steps",
readonly=True,
)

def cart_step_update(self, current_step=None, next_step=None):
vals = self._cart_step_update_vals(
current_step=current_step, next_step=next_step
)
if vals:
self.write(vals)

def _cart_step_update_vals(self, current_step=None, next_step=None):
vals = {}
if current_step:
vals["cart_step_done_ids"] = [
(4, self._cart_step_get_from_code(current_step).id, 0)
]
if next_step:
vals["cart_step_id"] = self._cart_step_get_from_code(next_step).id
return vals

def _cart_step_get_from_code(self, code):
step = self.env["sale.order.cart.step"].search([("code", "=", code)], limit=1)
if not step:
raise exceptions.UserError(_("Invalid step code %s") % code)
return step
19 changes: 19 additions & 0 deletions sale_cart_step/models/sale_order_cart_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <[email protected]>
# Copyright 2024 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models


class SaleOrderCartStep(models.Model):
_name = "sale.order.cart.step"
_description = "Cart Step"

name = fields.Char(required=True)
code = fields.Char(required=True, index=True)
active = fields.Boolean(default=True, copy=False)

_sql_constraints = [
("code_uniq", "unique (code, active)", "Active step code must be unique!")
]
1 change: 1 addition & 0 deletions sale_cart_step/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Simone Orsi <[email protected]>
1 change: 1 addition & 0 deletions sale_cart_step/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Provides a way to track checkout steps on sale orders of typology "cart".
3 changes: 3 additions & 0 deletions sale_cart_step/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_order_cart_step,access_sale_order_cart_step,model_sale_order_cart_step,sales_team.group_sale_salesman,1,1,1,1
access_sale_order_cart_step_employee,access_sale_order_cart_step_employee,model_sale_order_cart_step,,1,0,0,0
1 change: 1 addition & 0 deletions sale_cart_step/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_sale_cart_step
63 changes: 63 additions & 0 deletions sale_cart_step/tests/test_sale_cart_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import psycopg2

from odoo import exceptions
from odoo.tests.common import TransactionCase
from odoo.tools import mute_logger


class TestSaleCart(TransactionCase):
@classmethod
def setUpClass(cls):
super(TestSaleCart, cls).setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.product = cls.env["product.product"].create(
{
"name": "product",
"uom_id": cls.env.ref("uom.product_uom_unit").id,
}
)
cls.partner = cls.env["res.partner"].create({"name": "partner"})
cls.cart = cls.env["sale.order"].create(
{
"partner_id": cls.partner.id,
"order_line": [
(
0,
0,
{"product_id": cls.product.id, "product_uom_qty": 1},
)
],
"typology": "cart",
}
)
cls.address_step = cls.env.ref("sale_cart_step.cart_step_address")
cls.checkout_step = cls.env.ref("sale_cart_step.cart_step_checkout")
cls.last_step = cls.env.ref("sale_cart_step.cart_step_last")

def test_update_steps(self):
self.assertFalse(self.cart.cart_step_id)
self.assertFalse(self.cart.cart_step_done_ids)
self.cart.cart_step_update(
current_step=self.address_step.code, next_step=self.checkout_step.code
)
self.assertIn(self.address_step, self.cart.cart_step_done_ids)
self.assertEqual(self.cart.cart_step_id, self.checkout_step)
self.cart.cart_step_update(
current_step=self.checkout_step.code, next_step=self.last_step.code
)
self.assertIn(self.checkout_step, self.cart.cart_step_done_ids)
self.assertEqual(self.cart.cart_step_id, self.last_step)

def test_update_steps_bad_code(self):
with self.assertRaisesRegex(exceptions.UserError, "Invalid step code foo"):
self.cart.cart_step_update(current_step="foo")

@mute_logger("odoo.sql_db")
def test_uniq(self):
with self.assertRaises(psycopg2.errors.UniqueViolation):
self.last_step.copy()
self.last_step.active = False
self.assertTrue(self.last_step.copy())
58 changes: 58 additions & 0 deletions sale_cart_step/views/cart_step.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>

<record id="sale_order_cart_step_view_tree" model="ir.ui.view">
<field name="model">sale.order.cart.step</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name" />
<field name="code" />
</tree>
</field>
</record>

<record id="sale_order_cart_step_view_search" model="ir.ui.view">
<field name="model">sale.order.cart.step</field>
<field name="arch" type="xml">
<search>
<field name="name" />
<field name="code" />
<filter name="active" string="Active" domain="[('active','=',True)]" />
<filter
name="inactive"
string="Inactive"
domain="[('active','=',False)]"
/>
</search>
</field>
</record>

<record model="ir.actions.act_window" id="act_open_sale_order_cart_step_view">
<field name="name">Cart Steps</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sale.order.cart.step</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="sale_order_cart_step_view_search" />
<field name="domain">[]</field>
<field name="context">{}</field>
</record>

<record
model="ir.actions.act_window.view"
id="act_open_sale_order_cart_step_view_tree"
>
<field name="act_window_id" ref="act_open_sale_order_cart_step_view" />
<field name="sequence" eval="10" />
<field name="view_mode">tree</field>
<field name="view_id" ref="sale_order_cart_step_view_tree" />
</record>

<menuitem
id="menu_sale_order_cart_step"
name="Cart Steps"
parent="sale.menu_sales_config"
sequence="10"
action="act_open_sale_order_cart_step_view"
/>

</odoo>
25 changes: 25 additions & 0 deletions sale_cart_step/views/sale_order.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="sale_order_view_form" model="ir.ui.view">
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale_cart.sale_order_form_view" />
<field name="priority" eval="20" />
<field name="arch" type="xml">
<field name="typology" position="after">
<field
name="cart_step_id"
attrs="{'invisible': [('typology', '!=', 'cart')]}"
context="{'active_test': False}"
/>
<field
name="cart_step_done_ids"
widget="many2many_tags"
attrs="{'invisible': [('typology', '!=', 'cart')]}"
context="{'active_test': False}"
/>
</field>
</field>
</record>

</odoo>
1 change: 1 addition & 0 deletions setup/sale_cart_step/odoo/addons/sale_cart_step
6 changes: 6 additions & 0 deletions setup/sale_cart_step/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_api_cart_step/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,
)
1 change: 1 addition & 0 deletions shopinvader_api_cart_step/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bot pls :)
1 change: 1 addition & 0 deletions shopinvader_api_cart_step/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import schemas
14 changes: 14 additions & 0 deletions shopinvader_api_cart_step/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Sale Cart steps cart API integration",
"summary": """
Track checkout steps on sale cart.
""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Camptocamp",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"depends": ["sale_cart_step", "shopinvader_api_cart"],
}
1 change: 1 addition & 0 deletions shopinvader_api_cart_step/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Simone Orsi <[email protected]>
1 change: 1 addition & 0 deletions shopinvader_api_cart_step/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Plugs ``sale_cart_step`` within cart api.
2 changes: 2 additions & 0 deletions shopinvader_api_cart_step/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import cart
from . import sale
22 changes: 22 additions & 0 deletions shopinvader_api_cart_step/schemas/cart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2024 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.addons.shopinvader_api_cart.schemas import (
CartUpdateInput as BaseCartUpdateInput,
)


class CartUpdateInput(BaseCartUpdateInput, extends=True):

current_step: str | None = None
next_step: str | None = None

def convert_to_sale_write(self, cart):
vals = super().convert_to_sale_write(cart)
if self.current_step or self.next_step:
step_data = cart._cart_step_update_vals(
current_step=self.current_step, next_step=self.next_step
)
vals.update(step_data)
return vals
34 changes: 34 additions & 0 deletions shopinvader_api_cart_step/schemas/sale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from typing import List, Optional

from extendable_pydantic import StrictExtendableBaseModel

from odoo.addons.shopinvader_schema_sale.schemas import Sale as BaseSale


class CartStep(StrictExtendableBaseModel):
code: str
name: str

@classmethod
def from_sale_cart_step(cls, rec):
return {"name": rec.name, "code": rec.code} if rec else None

@classmethod
def from_sale_cart_steps(cls, recs):
return [cls.from_sale_cart_step(x) for x in recs]


class Sale(BaseSale, extends=True):

step: Optional[CartStep] = None
done_steps: Optional[List[CartStep]] = []

@classmethod
def from_sale_order(cls, odoo_rec):
obj = super().from_sale_order(odoo_rec)
obj.step = CartStep.from_sale_cart_step(odoo_rec.cart_step_id)
obj.done_steps = CartStep.from_sale_cart_steps(odoo_rec.cart_step_done_ids)
return obj
1 change: 1 addition & 0 deletions shopinvader_api_cart_step/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_api_cart_step
Loading

0 comments on commit b3d27b5

Please sign in to comment.