diff options
| author | Aurélien Warnon <awa@odoo.com> | 2019-02-11 12:32:19 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2019-02-11 17:46:40 +0000 |
| commit | 9b7bee73e5b6c09656c3720a5c9709f3948534c0 (patch) | |
| tree | 8ae9dccb279ec0c01800ec0dc1f9695a717c03f8 /addons | |
| parent | fb8126ddd7d0eb6a55435c1eadf99df6cf4fb658 (diff) | |
[ADD] website_sale_slides: allow to sell slide.channel
Task #1937160
Purpose
=======
This commit adds sale capabilities to a slide.channel. A slide.channel can
now have the 'payment' visibility, that requires a 'product_id' configured
on the channel.
When a customer purchases a product linked to a channel, he is added to the
members of the channel (see slide.channel.partner_ids) when his order is
confirmed.
The feature is added in a new module 'website_sale_slides' that comes as a
bridge auto-installed between 'website_slides' and 'website_sale'.
The final goal is to be able to sell "courses" (see task #1902304).
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/website_sale_slides/__init__.py | 4 | ||||
| -rw-r--r-- | addons/website_sale_slides/__manifest__.py | 17 | ||||
| -rw-r--r-- | addons/website_sale_slides/data/demo-thumbnails/5WMqwTnZ-qs.png | bin | 0 -> 196182 bytes | |||
| -rw-r--r-- | addons/website_sale_slides/data/demo-thumbnails/product_course.png | bin | 0 -> 109408 bytes | |||
| -rw-r--r-- | addons/website_sale_slides/data/demo-thumbnails/ptjeDDoURL8.png | bin | 0 -> 210254 bytes | |||
| -rw-r--r-- | addons/website_sale_slides/data/website_sale_slides_demo.xml | 46 | ||||
| -rw-r--r-- | addons/website_sale_slides/models/__init__.py | 4 | ||||
| -rw-r--r-- | addons/website_sale_slides/models/sale_order.py | 35 | ||||
| -rw-r--r-- | addons/website_sale_slides/models/slide_channel.py | 20 | ||||
| -rw-r--r-- | addons/website_sale_slides/tests/__init__.py | 4 | ||||
| -rw-r--r-- | addons/website_sale_slides/tests/test_course_purchase_flow.py | 46 | ||||
| -rw-r--r-- | addons/website_sale_slides/views/slide_channel_views.xml | 16 | ||||
| -rw-r--r-- | addons/website_slides/models/slide_channel.py | 14 |
13 files changed, 203 insertions, 3 deletions
diff --git a/addons/website_sale_slides/__init__.py b/addons/website_sale_slides/__init__.py new file mode 100644 index 00000000000..dc5e6b693d1 --- /dev/null +++ b/addons/website_sale_slides/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/website_sale_slides/__manifest__.py b/addons/website_sale_slides/__manifest__.py new file mode 100644 index 00000000000..59d15170b4b --- /dev/null +++ b/addons/website_sale_slides/__manifest__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': "Sell Courses", + 'summary': 'Sell your courses online', + 'description': """Sell your courses using the e-commerce features of the website.""", + 'category': 'Hidden', + 'version': '0.1', + + 'depends': ['website_slides', 'website_sale'], + 'installable': True, + 'auto_install': True, + 'data': [ + 'data/website_sale_slides_demo.xml', + 'views/slide_channel_views.xml', + ] +} diff --git a/addons/website_sale_slides/data/demo-thumbnails/5WMqwTnZ-qs.png b/addons/website_sale_slides/data/demo-thumbnails/5WMqwTnZ-qs.png Binary files differnew file mode 100644 index 00000000000..1bbec207f29 --- /dev/null +++ b/addons/website_sale_slides/data/demo-thumbnails/5WMqwTnZ-qs.png diff --git a/addons/website_sale_slides/data/demo-thumbnails/product_course.png b/addons/website_sale_slides/data/demo-thumbnails/product_course.png Binary files differnew file mode 100644 index 00000000000..db59564cebc --- /dev/null +++ b/addons/website_sale_slides/data/demo-thumbnails/product_course.png diff --git a/addons/website_sale_slides/data/demo-thumbnails/ptjeDDoURL8.png b/addons/website_sale_slides/data/demo-thumbnails/ptjeDDoURL8.png Binary files differnew file mode 100644 index 00000000000..dc3c43dd8a6 --- /dev/null +++ b/addons/website_sale_slides/data/demo-thumbnails/ptjeDDoURL8.png diff --git a/addons/website_sale_slides/data/website_sale_slides_demo.xml b/addons/website_sale_slides/data/website_sale_slides_demo.xml new file mode 100644 index 00000000000..554e7500133 --- /dev/null +++ b/addons/website_sale_slides/data/website_sale_slides_demo.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + <record id="product_course" model="product.product"> + <field name="name">Furniture creation course</field> + <field name="standard_price">100.0</field> + <field name="list_price">100.0</field> + <field name="type">service</field> + <field name="website_published" eval="True"/> + <field name="image" type="base64" file="website_sale_slides/data/demo-thumbnails/product_course.png"/> + </record> + + <record id="channel_on_payment" model="slide.channel"> + <field name="name">Furniture creation</field> + <field name="promote_strategy">most_viewed</field> + <field name="website_published" eval="True"/> + <field name="description">All you need to know about furniture creation.</field> + <field name="visibility">payment</field> + <field name="product_id" ref="product_course"/> + </record> + + <record id="slide_find_wood" model="slide.slide"> + <field name="name">How to find quality wood.</field> + <field name="url">https://www.youtube.com/watch?v=5WMqwTnZ-qs</field> + <field name="document_id">5WMqwTnZ-qs</field> + <field name="slide_type">video</field> + <field name="channel_id" ref="channel_on_payment"/> + <field name="website_published" eval="True"/> + <field name="is_preview" eval="True"/> + <field name="image" type="base64" file="website_sale_slides/data/demo-thumbnails/5WMqwTnZ-qs.png"/> + <field name="description">Learn of to identify quality wood in order to create solid furnitures.</field> + </record> + + <record id="slide_create_furniture" model="slide.slide"> + <field name="name">How to create your own piece of furniture.</field> + <field name="url">https://www.youtube.com/watch?v=ptjeDDoURL8</field> + <field name="document_id">ptjeDDoURL8</field> + <field name="slide_type">video</field> + <field name="channel_id" ref="channel_on_payment"/> + <field name="website_published" eval="True"/> + <field name="is_preview" eval="True"/> + <field name="image" type="base64" file="website_sale_slides/data/demo-thumbnails/ptjeDDoURL8.png"/> + <field name="description">From a piece of wood to a fully functional furniture, step by step.</field> + </record> + </data> +</odoo> diff --git a/addons/website_sale_slides/models/__init__.py b/addons/website_sale_slides/models/__init__.py new file mode 100644 index 00000000000..715f352d147 --- /dev/null +++ b/addons/website_sale_slides/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import slide_channel +from . import sale_order diff --git a/addons/website_sale_slides/models/sale_order.py b/addons/website_sale_slides/models/sale_order.py new file mode 100644 index 00000000000..880bd0636e6 --- /dev/null +++ b/addons/website_sale_slides/models/sale_order.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, api + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + @api.multi + def _action_confirm(self): + """ If the product of an order line is a 'course', we add the client of the sale_order + as a member of the channel(s) on which this product is configured (see slide.channel.product_id). """ + result = super(SaleOrder, self)._action_confirm() + + so_lines = self.env['sale.order.line'].search( + [('order_id', 'in', self.ids)] + ) + products = so_lines.mapped('product_id') + related_channels = self.env['slide.channel'].search( + [('product_id', 'in', products.ids)] + ) + channel_products = related_channels.mapped('product_id') + + channels_per_so = {sale_order: self.env['slide.channel'] for sale_order in self} + for so_line in so_lines: + if so_line.product_id in channel_products: + for related_channel in related_channels: + if related_channel.product_id == so_line.product_id: + channels_per_so[so_line.order_id] = channels_per_so[so_line.order_id] | related_channel + + for sale_order, channels in channels_per_so.items(): + channels._action_add_member(target_partner=sale_order.partner_id) + + return result diff --git a/addons/website_sale_slides/models/slide_channel.py b/addons/website_sale_slides/models/slide_channel.py new file mode 100644 index 00000000000..1947d15b08a --- /dev/null +++ b/addons/website_sale_slides/models/slide_channel.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields + + +class Channel(models.Model): + _inherit = 'slide.channel' + + visibility = fields.Selection(selection_add=[('payment', 'On payment')]) + product_id = fields.Many2one('product.product', 'Product', index=True) + + _sql_constraints = [ + ('product_id_check', "CHECK( visibility!='payment' OR product_id IS NOT NULL )", "Product is required for on payment channels.") + ] + + def _filter_add_member(self, target_user, **member_values): + """ Overridden to add 'payment' channels to the filtered channels """ + result = super(Channel, self)._filter_add_member(target_user, **member_values) + return result | self.filtered(lambda channel: channel.visibility == 'payment') diff --git a/addons/website_sale_slides/tests/__init__.py b/addons/website_sale_slides/tests/__init__.py new file mode 100644 index 00000000000..536fe88b96c --- /dev/null +++ b/addons/website_sale_slides/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_course_purchase_flow diff --git a/addons/website_sale_slides/tests/test_course_purchase_flow.py b/addons/website_sale_slides/tests/test_course_purchase_flow.py new file mode 100644 index 00000000000..c97a0269f93 --- /dev/null +++ b/addons/website_sale_slides/tests/test_course_purchase_flow.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.website_slides.tests import common + + +class TestCoursePurchaseFlow(common.SlidesCase): + def test_course_purchase_flow(self): + # Step1: create a course product and assign it to 2 slide.channels + course_product = self.env['product.product'].create({ + 'name': "Course Product", + 'standard_price': 100, + 'list_price': 150, + 'type': 'service', + 'invoice_policy': 'order', + }) + + self.channel.write({ + 'visibility': 'payment', + 'product_id': course_product.id + }) + + self.channel_2 = self.env['slide.channel'].sudo(self.user_publisher).create({ + 'name': 'Test Channel', + 'visibility': 'payment', + 'product_id': course_product.id + }) + + # Step 2: create a sale_order with the course product + sale_order = self.env['sale.order'].create({ + 'partner_id': self.customer.id, + 'order_line': [ + (0, 0, { + 'name': course_product.name, + 'product_id': course_product.id, + 'product_uom_qty': 1, + 'price_unit': course_product.list_price, + }) + ], + }) + + sale_order.action_confirm() + + # Step 3: check that the customer is now a member of both channel + self.assertIn(self.customer, self.channel.partner_ids) + self.assertIn(self.customer, self.channel_2.partner_ids) diff --git a/addons/website_sale_slides/views/slide_channel_views.xml b/addons/website_sale_slides/views/slide_channel_views.xml new file mode 100644 index 00000000000..cbf499cc6e7 --- /dev/null +++ b/addons/website_sale_slides/views/slide_channel_views.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + <record id="slide_channel_view_form" model="ir.ui.view"> + <field name="name">slide.channel.view.form.inherit.sale</field> + <field name="model">slide.channel</field> + <field name="inherit_id" ref="website_slides.view_slide_channel_form"/> + <field name="arch" type="xml"> + <xpath expr="//field[@name='visibility']" position="after"> + <field name="product_id" + attrs="{'invisible': [('visibility', '!=', 'payment')], 'required': [('visibility', '=', 'payment')]}" /> + </xpath> + </field> + </record> + </data> +</odoo> diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index cad83a33b7e..9c7fcef352c 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -250,10 +250,18 @@ class Channel(models.Model): # --------------------------------------------------------- def action_add_member(self, **member_values): - new_cp = self._action_add_member(target_partner=self.env.user.partner_id, **member_values) - return bool(new_cp) + """ Adds the logged in user in the channel members. + (see '_action_add_member' for more info) - def _action_add_member(self, target_partner, **member_values): + Returns True if added successfully, False otherwise.""" + return bool(self._action_add_member(target_partner=self.env.user.partner_id, **member_values)) + + def _action_add_member(self, target_partner=False, **member_values): + """ Add the target_partner as a member of the channel (to its slide.channel.partner). + This will make the content (slides) of the channel available to that partner. + + Returns the added 'slide.channel.partner's (! as sudo !) + """ existing = self.env['slide.channel.partner'].sudo().search([ ('channel_id', 'in', self.ids), ('partner_id', '=', target_partner.id) |
