diff --git a/addons/website_sale_slides/__manifest__.py b/addons/website_sale_slides/__manifest__.py index 4a0ab8ae952..3ef082aca44 100644 --- a/addons/website_sale_slides/__manifest__.py +++ b/addons/website_sale_slides/__manifest__.py @@ -10,6 +10,7 @@ 'depends': ['website_slides', 'website_sale'], 'installable': True, 'data': [ + 'data/product_data.xml', 'report/sale_report_views.xml', 'views/website_slides_menu_views.xml', 'views/slide_channel_views.xml', @@ -25,6 +26,9 @@ 'web.assets_frontend': [ 'website_sale_slides/static/src/js/**/*', ], + 'web.assets_qweb': [ + 'website_sale_slides/static/src/xml/website_slides_channel.xml', + ] }, 'license': 'LGPL-3', } diff --git a/addons/website_sale_slides/controllers/slides.py b/addons/website_sale_slides/controllers/slides.py index 3debae40eef..67b76bd1f6a 100644 --- a/addons/website_sale_slides/controllers/slides.py +++ b/addons/website_sale_slides/controllers/slides.py @@ -2,11 +2,22 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.website_slides.controllers.main import WebsiteSlides -from odoo.http import request +from odoo.http import request, route +from odoo.tools import format_amount class WebsiteSaleSlides(WebsiteSlides): + @route('/slides/get_course_products', type='json', auth='user') + def get_course_products(self): + """Return a list of the course products values with formatted price.""" + products = request.env['product.product'].search([('detailed_type', '=', 'course')]) + + return [{ + 'id': product.id, + 'name': f'{product.name} ({format_amount(request.env, product.list_price, product.currency_id)})', + } for product in products] + def _prepare_additional_channel_values(self, values, **kwargs): values = super(WebsiteSaleSlides, self)._prepare_additional_channel_values(values, **kwargs) channel = values['channel'] @@ -15,3 +26,13 @@ class WebsiteSaleSlides(WebsiteSlides): values['product_info'] = channel.product_id.product_tmpl_id._get_combination_info(product_id=channel.product_id.id, pricelist=pricelist) values['product_info']['currency_id'] = request.website.currency_id return values + + def _slide_channel_prepare_values(self, **kwargs): + """Parse the values posted when we create a new course + from website to add the selected product. + """ + channel = super(WebsiteSaleSlides, self)._slide_channel_prepare_values(**kwargs) + channel['enroll'] = kwargs.get('enroll') + if channel['enroll'] == 'payment' and 'product_id' in kwargs: + channel['product_id'] = int(kwargs['product_id']) + return channel diff --git a/addons/website_sale_slides/data/product_data.xml b/addons/website_sale_slides/data/product_data.xml new file mode 100644 index 00000000000..82d60e5339a --- /dev/null +++ b/addons/website_sale_slides/data/product_data.xml @@ -0,0 +1,17 @@ + + + + Courses + + + + Course Access + 99.99 + 99.99 + course + order + + + + + diff --git a/addons/website_sale_slides/data/product_demo.xml b/addons/website_sale_slides/data/product_demo.xml index 90ed00688f6..95f549df859 100644 --- a/addons/website_sale_slides/data/product_demo.xml +++ b/addons/website_sale_slides/data/product_demo.xml @@ -6,7 +6,7 @@ Taking care of Trees Course 150.0 150.0 - service + course order @@ -18,7 +18,7 @@ DIY Furniture Course 100.0 100.0 - service + course order diff --git a/addons/website_sale_slides/models/__init__.py b/addons/website_sale_slides/models/__init__.py index a7ae607df42..848605c053e 100644 --- a/addons/website_sale_slides/models/__init__.py +++ b/addons/website_sale_slides/models/__init__.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- from . import product_product -from . import slide_channel +from . import product_template from . import sale_order +from . import slide_channel +from . import website diff --git a/addons/website_sale_slides/models/product_product.py b/addons/website_sale_slides/models/product_product.py index 94fc0c6e82b..7d3cacf6d35 100644 --- a/addons/website_sale_slides/models/product_product.py +++ b/addons/website_sale_slides/models/product_product.py @@ -1,10 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import fields, models +from odoo import _, fields, models class Product(models.Model): _inherit = "product.product" channel_ids = fields.One2many('slide.channel', 'product_id', string='Courses') + + def get_product_multiline_description_sale(self): + payment_channels = self.channel_ids.filtered(lambda course: course.enroll == 'payment') + + if not payment_channels: + return super(Product, self).get_product_multiline_description_sale() + + return _('Access to:\n%s', '\n'.join(payment_channels.mapped('name'))) diff --git a/addons/website_sale_slides/models/product_template.py b/addons/website_sale_slides/models/product_template.py new file mode 100644 index 00000000000..caad6854d95 --- /dev/null +++ b/addons/website_sale_slides/models/product_template.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + detailed_type = fields.Selection(selection_add=[ + ('course', 'Course'), + ], ondelete={'course': 'set service'}) + + def _detailed_type_mapping(self): + type_mapping = super(ProductTemplate, self)._detailed_type_mapping() + type_mapping['course'] = 'service' + return type_mapping diff --git a/addons/website_sale_slides/models/sale_order.py b/addons/website_sale_slides/models/sale_order.py index 03e345df922..08646c8df4c 100644 --- a/addons/website_sale_slides/models/sale_order.py +++ b/addons/website_sale_slides/models/sale_order.py @@ -17,7 +17,7 @@ class SaleOrder(models.Model): ) products = so_lines.mapped('product_id') related_channels = self.env['slide.channel'].search( - [('product_id', 'in', products.ids)] + [('product_id', 'in', products.ids), ('enroll', '=', 'payment')], ) channel_products = related_channels.mapped('product_id') diff --git a/addons/website_sale_slides/models/slide_channel.py b/addons/website_sale_slides/models/slide_channel.py index 37d158e0898..da503a966ef 100644 --- a/addons/website_sale_slides/models/slide_channel.py +++ b/addons/website_sale_slides/models/slide_channel.py @@ -7,10 +7,16 @@ from odoo import api, fields, models class Channel(models.Model): _inherit = 'slide.channel' + def _get_default_product_id(self): + product_courses = self.env['product.product'].search( + [('detailed_type', '=', 'course')], limit=2) + return product_courses.id if len(product_courses) == 1 else False + enroll = fields.Selection(selection_add=[ ('payment', 'On payment') ], ondelete={'payment': lambda recs: recs.write({'enroll': 'invite'})}) - product_id = fields.Many2one('product.product', 'Product', index=True) + product_id = fields.Many2one('product.product', 'Product', domain=[('detailed_type', '=', 'course')], + default=_get_default_product_id) product_sale_revenues = fields.Monetary( string='Total revenues', compute='_compute_product_sale_revenues', groups="sales_team.group_sale_salesman") diff --git a/addons/website_sale_slides/models/website.py b/addons/website_sale_slides/models/website.py new file mode 100644 index 00000000000..e110e51a26e --- /dev/null +++ b/addons/website_sale_slides/models/website.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models +from odoo.osv import expression + + +class Website(models.Model): + _inherit = 'website' + + def sale_product_domain(self): + return expression.AND([ + super(Website, self).sale_product_domain(), + [('detailed_type', '!=', 'course')], + ]) diff --git a/addons/website_sale_slides/static/img/default_course_product.svg b/addons/website_sale_slides/static/img/default_course_product.svg new file mode 100644 index 00000000000..67682f913b3 --- /dev/null +++ b/addons/website_sale_slides/static/img/default_course_product.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/addons/website_sale_slides/static/src/js/website_sale_slides_editor.js b/addons/website_sale_slides/static/src/js/website_sale_slides_editor.js new file mode 100644 index 00000000000..349ca3793c4 --- /dev/null +++ b/addons/website_sale_slides/static/src/js/website_sale_slides_editor.js @@ -0,0 +1,26 @@ +/** @odoo-module **/ + +import {ChannelCreateDialog} from '@website_slides/js/website_slides.editor'; + +ChannelCreateDialog.include({ + xmlDependencies: ChannelCreateDialog.prototype.xmlDependencies.concat( + ['/website_sale_slides/static/src/xml/website_slides_channel.xml'] + ), + + events: _.extend({}, ChannelCreateDialog.prototype.events, { + 'change input[name="enroll"]': '_onEnrollChanged', + }), + + willStart: async function () { + await this._super(); + + this.products = await this._rpc({route: '/slides/get_course_products'}); + }, + + /** + * @private + */ + _onEnrollChanged: function (ev) { + this.$('.o_wslides_course_products').toggleClass('d-none', ev.target.value !== 'payment'); + }, +}); diff --git a/addons/website_sale_slides/static/src/xml/website_slides_channel.xml b/addons/website_sale_slides/static/src/xml/website_slides_channel.xml new file mode 100644 index 00000000000..1b03ebccf96 --- /dev/null +++ b/addons/website_sale_slides/static/src/xml/website_slides_channel.xml @@ -0,0 +1,52 @@ + + + + + + +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+ +
+
+
+
diff --git a/addons/website_sale_slides/views/slide_channel_views.xml b/addons/website_sale_slides/views/slide_channel_views.xml index d334b8931f2..3cb54e7316f 100644 --- a/addons/website_sale_slides/views/slide_channel_views.xml +++ b/addons/website_sale_slides/views/slide_channel_views.xml @@ -8,7 +8,7 @@ + context="{'default_detailed_type': 'course', 'default_invoice_policy': 'order', 'default_purchase_ok': False, 'default_sale_ok': True, 'default_website_published': True}"/>