From 59eae1d7d55da672da0dbd7600247b0becaab8b8 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Mon, 20 Mar 2023 15:58:24 +0000 Subject: [PATCH 1/6] [IMP] website_sale: right place for menus definition Part-of: odoo/odoo#116026 --- .../website_sale/views/website_sale_menus.xml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/addons/website_sale/views/website_sale_menus.xml b/addons/website_sale/views/website_sale_menus.xml index 532f8aee44f..1b5d086f7d7 100644 --- a/addons/website_sale/views/website_sale_menus.xml +++ b/addons/website_sale/views/website_sale_menus.xml @@ -75,6 +75,12 @@ + + @@ -91,17 +97,4 @@ parent="website.menu_content" sequence="30"/> - - - - From 868b8c9f5ce4c99e3dac57b391cc122313761c4a Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 21 Mar 2023 11:16:21 +0000 Subject: [PATCH 2/6] [CLN] website_sale_loyalty: xml cleanup Part-of: odoo/odoo#116026 --- addons/website_sale_loyalty/__manifest__.py | 10 +++++---- .../views/loyalty_program_views.xml | 21 ------------------- .../views/website_sale_loyalty_menus.xml | 17 +++++++++++++++ .../website_sale_loyalty/wizard/__init__.py | 3 +-- .../{sale_coupon_share.py => coupon_share.py} | 3 +-- ...share_views.xml => coupon_share_views.xml} | 0 .../res_config_settings_views.xml | 14 +++++++++---- 7 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 addons/website_sale_loyalty/views/website_sale_loyalty_menus.xml rename addons/website_sale_loyalty/wizard/{sale_coupon_share.py => coupon_share.py} (98%) rename addons/website_sale_loyalty/wizard/{sale_coupon_share_views.xml => coupon_share_views.xml} (100%) rename addons/website_sale_loyalty/{views => wizard}/res_config_settings_views.xml (60%) diff --git a/addons/website_sale_loyalty/__manifest__.py b/addons/website_sale_loyalty/__manifest__.py index f1664682164..a58179a2061 100644 --- a/addons/website_sale_loyalty/__manifest__.py +++ b/addons/website_sale_loyalty/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. { 'name': "Coupons, Promotions, Gift Card and Loyalty for eCommerce", @@ -13,12 +12,15 @@ Coupon & promotion programs can be edited in the Catalog menu of the Website app 'depends': ['website_sale', 'website_links', 'sale_loyalty'], 'data': [ 'security/ir.model.access.csv', - 'wizard/sale_coupon_share_views.xml', + 'views/loyalty_card_views.xml', 'views/loyalty_program_views.xml', - 'views/website_sale_templates.xml', - 'views/res_config_settings_views.xml', 'views/snippets.xml', + 'views/website_sale_templates.xml', + 'views/website_sale_loyalty_menus.xml', + + 'wizard/coupon_share_views.xml', + 'wizard/res_config_settings_views.xml', ], 'demo': [ 'data/product_demo.xml', diff --git a/addons/website_sale_loyalty/views/loyalty_program_views.xml b/addons/website_sale_loyalty/views/loyalty_program_views.xml index d0e1cb4af17..38f5d36cc6b 100644 --- a/addons/website_sale_loyalty/views/loyalty_program_views.xml +++ b/addons/website_sale_loyalty/views/loyalty_program_views.xml @@ -1,26 +1,5 @@ - - - - - loyalty.program.view.form.inherit.website.sale.loyalty diff --git a/addons/website_sale_loyalty/views/website_sale_loyalty_menus.xml b/addons/website_sale_loyalty/views/website_sale_loyalty_menus.xml new file mode 100644 index 00000000000..dfd210d564b --- /dev/null +++ b/addons/website_sale_loyalty/views/website_sale_loyalty_menus.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/addons/website_sale_loyalty/wizard/__init__.py b/addons/website_sale_loyalty/wizard/__init__.py index 4731e9ff622..278dedd47c5 100644 --- a/addons/website_sale_loyalty/wizard/__init__.py +++ b/addons/website_sale_loyalty/wizard/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import sale_coupon_share +from . import coupon_share diff --git a/addons/website_sale_loyalty/wizard/sale_coupon_share.py b/addons/website_sale_loyalty/wizard/coupon_share.py similarity index 98% rename from addons/website_sale_loyalty/wizard/sale_coupon_share.py rename to addons/website_sale_loyalty/wizard/coupon_share.py index f2adbcf5cb4..52fa155dead 100644 --- a/addons/website_sale_loyalty/wizard/sale_coupon_share.py +++ b/addons/website_sale_loyalty/wizard/coupon_share.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from werkzeug.urls import url_encode @@ -7,7 +6,7 @@ from odoo import fields, models, api, _ from odoo.exceptions import UserError, ValidationError -class SaleCouponShare(models.TransientModel): +class CouponShare(models.TransientModel): _name = 'coupon.share' _description = 'Create links that apply a coupon and redirect to a specific page' diff --git a/addons/website_sale_loyalty/wizard/sale_coupon_share_views.xml b/addons/website_sale_loyalty/wizard/coupon_share_views.xml similarity index 100% rename from addons/website_sale_loyalty/wizard/sale_coupon_share_views.xml rename to addons/website_sale_loyalty/wizard/coupon_share_views.xml diff --git a/addons/website_sale_loyalty/views/res_config_settings_views.xml b/addons/website_sale_loyalty/wizard/res_config_settings_views.xml similarity index 60% rename from addons/website_sale_loyalty/views/res_config_settings_views.xml rename to addons/website_sale_loyalty/wizard/res_config_settings_views.xml index 5d5cfee8a5e..c20c2109eaa 100644 --- a/addons/website_sale_loyalty/views/res_config_settings_views.xml +++ b/addons/website_sale_loyalty/wizard/res_config_settings_views.xml @@ -1,17 +1,23 @@ + res.config.settings.view.form.inherit.website.sale.loyalty res.config.settings - + - +
-
-
+
+
From cd47fd451ee66cf8a4af23865fa031daa290cb2b Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 21 Mar 2023 11:20:59 +0000 Subject: [PATCH 3/6] [CLN] website_sale_digital: split product.py (1) Part-of: odoo/odoo#116026 --- .../website_sale_digital/models/__init__.py | 6 +- .../models/{product.py => product_product.py} | 15 +++-- .../models/product_template.py | 62 +++++++++++++++++++ 3 files changed, 72 insertions(+), 11 deletions(-) rename addons/website_sale_digital/models/{product.py => product_product.py} (85%) create mode 100644 addons/website_sale_digital/models/product_template.py diff --git a/addons/website_sale_digital/models/__init__.py b/addons/website_sale_digital/models/__init__.py index dc2af98c7f4..4efa7114347 100644 --- a/addons/website_sale_digital/models/__init__.py +++ b/addons/website_sale_digital/models/__init__.py @@ -1,6 +1,6 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import ir_attachment from . import account_invoice -from . import product +from . import ir_attachment +from . import product_product +from . import product_template diff --git a/addons/website_sale_digital/models/product.py b/addons/website_sale_digital/models/product_product.py similarity index 85% rename from addons/website_sale_digital/models/product.py rename to addons/website_sale_digital/models/product_product.py index ec6329b80c0..db9279a2ac3 100644 --- a/addons/website_sale_digital/models/product.py +++ b/addons/website_sale_digital/models/product_product.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ @@ -11,7 +10,7 @@ class ProductTemplate(models.Model): def _compute_attachment_count(self): attachment_data = self.env['ir.attachment']._read_group([('res_model', '=', self._name), ('res_id', 'in', self.ids), ('product_downloadable', '=', True)], ['res_id'], ['res_id']) - mapped_data = dict([(data['res_id'], data['res_id_count']) for data in attachment_data]) + mapped_data = {data['res_id']: data['res_id_count'] for data in attachment_data} for product_template in self: product_template.attachment_count = mapped_data.get(product_template.id, 0) @@ -25,9 +24,9 @@ class ProductTemplate(models.Model): 'view_mode': 'kanban,form', 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), 'help': """ -

%s

-

%s

- """ % (_("Add attachments for this digital product"), +

{}

+

{}

+ """.format(_("Add attachments for this digital product"), _("The attached files are the ones that will be purchased and sent to the customer.")), } @@ -56,8 +55,8 @@ class Product(models.Model): 'view_mode': 'kanban,form', 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), 'help': """ -

%s

-

%s

- """ % (_("Add attachments for this digital product"), +

{}

+

{}

+ """.format(_("Add attachments for this digital product"), _("The attached files are the ones that will be purchased and sent to the customer.")), } diff --git a/addons/website_sale_digital/models/product_template.py b/addons/website_sale_digital/models/product_template.py new file mode 100644 index 00000000000..db9279a2ac3 --- /dev/null +++ b/addons/website_sale_digital/models/product_template.py @@ -0,0 +1,62 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models, _ + + +class ProductTemplate(models.Model): + _inherit = ['product.template'] + + attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") + + def _compute_attachment_count(self): + attachment_data = self.env['ir.attachment']._read_group([('res_model', '=', self._name), ('res_id', 'in', self.ids), ('product_downloadable', '=', True)], ['res_id'], ['res_id']) + mapped_data = {data['res_id']: data['res_id_count'] for data in attachment_data} + for product_template in self: + product_template.attachment_count = mapped_data.get(product_template.id, 0) + + def action_open_attachments(self): + self.ensure_one() + return { + 'name': _('Digital Attachments'), + 'domain': [('res_model', '=', self._name), ('res_id', '=', self.id), ('product_downloadable', '=', True)], + 'res_model': 'ir.attachment', + 'type': 'ir.actions.act_window', + 'view_mode': 'kanban,form', + 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), + 'help': """ +

{}

+

{}

+ """.format(_("Add attachments for this digital product"), + _("The attached files are the ones that will be purchased and sent to the customer.")), + } + + +class Product(models.Model): + _inherit = 'product.product' + + attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") + + def _compute_attachment_count(self): + for product in self: + product.attachment_count = self.env['ir.attachment'].search_count([ + '|', + '&', '&', ('res_model', '=', 'product.template'), ('res_id', '=', product.product_tmpl_id.id), ('product_downloadable', '=', True), + '&', '&', ('res_model', '=', 'product.product'), ('res_id', '=', product.id), ('product_downloadable', '=', True)]) + + def action_open_attachments(self): + self.ensure_one() + return { + 'name': _('Digital Attachments'), + 'domain': [('product_downloadable', '=', True), '|', + '&', ('res_model', '=', 'product.template'), ('res_id', '=', self.product_tmpl_id.id), + '&', ('res_model', '=', self._name), ('res_id', '=', self.id)], + 'res_model': 'ir.attachment', + 'type': 'ir.actions.act_window', + 'view_mode': 'kanban,form', + 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), + 'help': """ +

{}

+

{}

+ """.format(_("Add attachments for this digital product"), + _("The attached files are the ones that will be purchased and sent to the customer.")), + } From a38a87d3a1716861f46f967e25c23baf9357c7da Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 21 Mar 2023 11:22:17 +0000 Subject: [PATCH 4/6] [CLN] website_sale_digital: split product.py (2) Part-of: odoo/odoo#116026 --- .../models/product_product.py | 32 ++--------------- .../models/product_template.py | 35 ++----------------- 2 files changed, 4 insertions(+), 63 deletions(-) diff --git a/addons/website_sale_digital/models/product_product.py b/addons/website_sale_digital/models/product_product.py index db9279a2ac3..49d27f7230a 100644 --- a/addons/website_sale_digital/models/product_product.py +++ b/addons/website_sale_digital/models/product_product.py @@ -1,37 +1,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models, _ +from odoo import fields, models, _ -class ProductTemplate(models.Model): - _inherit = ['product.template'] - - attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") - - def _compute_attachment_count(self): - attachment_data = self.env['ir.attachment']._read_group([('res_model', '=', self._name), ('res_id', 'in', self.ids), ('product_downloadable', '=', True)], ['res_id'], ['res_id']) - mapped_data = {data['res_id']: data['res_id_count'] for data in attachment_data} - for product_template in self: - product_template.attachment_count = mapped_data.get(product_template.id, 0) - - def action_open_attachments(self): - self.ensure_one() - return { - 'name': _('Digital Attachments'), - 'domain': [('res_model', '=', self._name), ('res_id', '=', self.id), ('product_downloadable', '=', True)], - 'res_model': 'ir.attachment', - 'type': 'ir.actions.act_window', - 'view_mode': 'kanban,form', - 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), - 'help': """ -

{}

-

{}

- """.format(_("Add attachments for this digital product"), - _("The attached files are the ones that will be purchased and sent to the customer.")), - } - - -class Product(models.Model): +class ProductProduct(models.Model): _inherit = 'product.product' attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") diff --git a/addons/website_sale_digital/models/product_template.py b/addons/website_sale_digital/models/product_template.py index db9279a2ac3..c2b8e4de819 100644 --- a/addons/website_sale_digital/models/product_template.py +++ b/addons/website_sale_digital/models/product_template.py @@ -1,10 +1,10 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models, _ +from odoo import fields, models, _ class ProductTemplate(models.Model): - _inherit = ['product.template'] + _inherit = 'product.template' attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") @@ -29,34 +29,3 @@ class ProductTemplate(models.Model): """.format(_("Add attachments for this digital product"), _("The attached files are the ones that will be purchased and sent to the customer.")), } - - -class Product(models.Model): - _inherit = 'product.product' - - attachment_count = fields.Integer(compute='_compute_attachment_count', string="File") - - def _compute_attachment_count(self): - for product in self: - product.attachment_count = self.env['ir.attachment'].search_count([ - '|', - '&', '&', ('res_model', '=', 'product.template'), ('res_id', '=', product.product_tmpl_id.id), ('product_downloadable', '=', True), - '&', '&', ('res_model', '=', 'product.product'), ('res_id', '=', product.id), ('product_downloadable', '=', True)]) - - def action_open_attachments(self): - self.ensure_one() - return { - 'name': _('Digital Attachments'), - 'domain': [('product_downloadable', '=', True), '|', - '&', ('res_model', '=', 'product.template'), ('res_id', '=', self.product_tmpl_id.id), - '&', ('res_model', '=', self._name), ('res_id', '=', self.id)], - 'res_model': 'ir.attachment', - 'type': 'ir.actions.act_window', - 'view_mode': 'kanban,form', - 'context': "{'default_res_model': '%s','default_res_id': %d, 'default_product_downloadable': True}" % (self._name, self.id), - 'help': """ -

{}

-

{}

- """.format(_("Add attachments for this digital product"), - _("The attached files are the ones that will be purchased and sent to the customer.")), - } From a7b065b445cea73ff47d56ddc4d65009256abd66 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 21 Mar 2023 11:25:01 +0000 Subject: [PATCH 5/6] [CLN] website_sale_digital: account_invoice.py * Right file name * Right class name * privatize method not meant to be called in rpc Part-of: odoo/odoo#116026 --- addons/website_sale_digital/controllers/main.py | 5 ++--- addons/website_sale_digital/models/__init__.py | 2 +- .../models/{account_invoice.py => account_move_line.py} | 6 ++---- 3 files changed, 5 insertions(+), 8 deletions(-) rename addons/website_sale_digital/models/{account_invoice.py => account_move_line.py} (91%) diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py index d1a4b777085..c8520e70ac9 100644 --- a/addons/website_sale_digital/controllers/main.py +++ b/addons/website_sale_digital/controllers/main.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 @@ -16,7 +15,7 @@ class WebsiteSaleDigital(CustomerPortal): @http.route() def portal_order_page(self, order_id=None, **post): - response = super(WebsiteSaleDigital, self).portal_order_page(order_id=order_id, **post) + response = super().portal_order_page(order_id=order_id, **post) if not 'sale_order' in response.qcontext: return response order = response.qcontext['sale_order'] @@ -68,7 +67,7 @@ class WebsiteSaleDigital(CustomerPortal): # Check if the user has bought the associated product res_model = attachment['res_model'] res_id = attachment['res_id'] - purchased_products = request.env['account.move.line'].get_digital_purchases() + purchased_products = request.env['account.move.line']._get_digital_purchases() if res_model == 'product.product': if res_id not in purchased_products: diff --git a/addons/website_sale_digital/models/__init__.py b/addons/website_sale_digital/models/__init__.py index 4efa7114347..987b812274d 100644 --- a/addons/website_sale_digital/models/__init__.py +++ b/addons/website_sale_digital/models/__init__.py @@ -1,6 +1,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import account_invoice +from . import account_move_line from . import ir_attachment from . import product_product from . import product_template diff --git a/addons/website_sale_digital/models/account_invoice.py b/addons/website_sale_digital/models/account_move_line.py similarity index 91% rename from addons/website_sale_digital/models/account_invoice.py rename to addons/website_sale_digital/models/account_move_line.py index a79f3c7cceb..c14e6b5a6b7 100644 --- a/addons/website_sale_digital/models/account_invoice.py +++ b/addons/website_sale_digital/models/account_move_line.py @@ -1,14 +1,12 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import models -class AccountInvoiceLine(models.Model): - +class AccountMoveLine(models.Model): _inherit = ['account.move.line'] - def get_digital_purchases(self): + def _get_digital_purchases(self): partner = self.env.user.partner_id # Get paid invoices From 2c4ff85fd438fabefc4daac96a159a499604a11b Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 21 Mar 2023 11:30:29 +0000 Subject: [PATCH 6/6] [CLN] website_sale_digital: cleanups unused imports unnecessary module in xml ids ... Part-of: odoo/odoo#116026 --- addons/website_sale_digital/controllers/main.py | 14 +++----------- addons/website_sale_digital/data/product_demo.xml | 4 ++-- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py index c8520e70ac9..b8f56905a30 100644 --- a/addons/website_sale_digital/controllers/main.py +++ b/addons/website_sale_digital/controllers/main.py @@ -1,19 +1,13 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -import base64 -import io -import os -import mimetypes - -from odoo import http -from odoo.http import request +from odoo.http import request, route from odoo.addons.sale.controllers.portal import CustomerPortal class WebsiteSaleDigital(CustomerPortal): orders_page = '/my/orders' - @http.route() + @route() def portal_order_page(self, order_id=None, **post): response = super().portal_order_page(order_id=order_id, **post) if not 'sale_order' in response.qcontext: @@ -49,9 +43,7 @@ class WebsiteSaleDigital(CustomerPortal): }) return response - @http.route([ - '/my/download', - ], type='http', auth='public') + @route(['/my/download'], type='http', auth='public') def download_attachment(self, attachment_id): # Check if this is a valid attachment id attachment = request.env['ir.attachment'].sudo().search_read( diff --git a/addons/website_sale_digital/data/product_demo.xml b/addons/website_sale_digital/data/product_demo.xml index 0da916826cb..671d34859da 100644 --- a/addons/website_sale_digital/data/product_demo.xml +++ b/addons/website_sale_digital/data/product_demo.xml @@ -1,7 +1,7 @@ - + eBook: Office Renovation for Dummies 2 4.50 @@ -11,7 +11,7 @@ - + ebook.pdf binary