diff --git a/addons/product/__init__.py b/addons/product/__init__.py index c072b1a6890..2a8e352ba2e 100644 --- a/addons/product/__init__.py +++ b/addons/product/__init__.py @@ -4,3 +4,4 @@ from . import models from . import report from . import populate +from . import wizard diff --git a/addons/product/__manifest__.py b/addons/product/__manifest__.py index 09790ddbffa..9e2e25721ca 100644 --- a/addons/product/__manifest__.py +++ b/addons/product/__manifest__.py @@ -30,6 +30,7 @@ Print product labels with barcode. 'data/product_data.xml', 'security/product_security.xml', 'security/ir.model.access.csv', + 'wizard/product_label_layout_views.xml', 'views/res_config_settings_views.xml', 'views/product_attribute_views.xml', 'views/product_views.xml', @@ -40,7 +41,7 @@ Print product labels with barcode. 'report/product_product_templates.xml', 'report/product_template_templates.xml', 'report/product_packaging.xml', - 'report/product_pricelist_report_templates.xml' + 'report/product_pricelist_report_templates.xml', ], 'demo': [ 'data/product_demo.xml', @@ -51,6 +52,9 @@ Print product labels with barcode. 'web.assets_backend': [ 'product/static/src/js/**/*', ], + 'web.report_assets_common': [ + 'product/static/src/scss/report_label_sheet.scss', + ], 'web.qunit_suite_tests': [ 'product/static/tests/**/*', ], diff --git a/addons/product/models/product.py b/addons/product/models/product.py index d21afe1d566..f937ea3f849 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -596,6 +596,11 @@ class ProductProduct(models.Model): ) return super().view_header_get(view_id, view_type) + def action_open_label_layout(self): + action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout') + action['context'] = {'default_product_ids': self.ids} + return action + def open_pricelist_rules(self): self.ensure_one() domain = ['|', diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 785657b11ae..c5c1e11184f 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -528,6 +528,11 @@ class ProductTemplate(models.Model): '', args=[('id', 'in', list(searched_ids))], operator='ilike', limit=limit, name_get_uid=name_get_uid) + def action_open_label_layout(self): + action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout') + action['context'] = {'default_product_tmpl_ids': self.ids} + return action + def open_pricelist_rules(self): self.ensure_one() domain = ['|', diff --git a/addons/product/report/__init__.py b/addons/product/report/__init__.py index 537678882bf..107ceeafd85 100644 --- a/addons/product/report/__init__.py +++ b/addons/product/report/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import product_label_report from . import product_pricelist_report diff --git a/addons/product/report/product_label_report.py b/addons/product/report/product_label_report.py new file mode 100644 index 00000000000..7ee922fa1e9 --- /dev/null +++ b/addons/product/report/product_label_report.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import _, models +from odoo.exceptions import UserError + +def _prepare_data(env, data): + # change product ids by actual product object to get access to fields in xml template + # we needed to pass ids because reports only accepts native python types (int, float, strings, ...) + if data.get('active_model') == 'product.template': + quantity_by_product = {env['product.template'].with_context(display_default_code=False).browse(int(p)): q for p, q in data.get('quantity_by_product').items()} + elif data.get('active_model') == 'product.product': + quantity_by_product = {env['product.product'].with_context(display_default_code=False).browse(int(p)): q for p, q in data.get('quantity_by_product').items()} + else: + raise UserError(_('Product model not defined, Please contact your administrator.')) + layout_wizard = env['product.label.layout'].browse(data.get('layout_wizard')) + if not layout_wizard: + return {} + + return { + 'quantity': quantity_by_product, + 'rows': layout_wizard.rows, + 'columns': layout_wizard.columns, + 'page_numbers': (sum(quantity_by_product.values()) - 1) // (layout_wizard.rows * layout_wizard.columns) + 1, + 'price_included': data.get('price_included'), + 'extra_html': layout_wizard.extra_html, + } + +class ReportProductTemplateLabel(models.AbstractModel): + _name = 'report.product.report_producttemplatelabel' + _description = 'Product Label Report' + + def _get_report_values(self, docids, data): + return _prepare_data(self.env, data) + +class ReportProductTemplateLabelDymo(models.AbstractModel): + _name = 'report.product.report_producttemplatelabel_dymo' + _description = 'Product Label Report' + + def _get_report_values(self, docids, data): + return _prepare_data(self.env, data) diff --git a/addons/product/report/product_product_templates.xml b/addons/product/report/product_product_templates.xml index 822f3b415d6..4635790d275 100644 --- a/addons/product/report/product_product_templates.xml +++ b/addons/product/report/product_product_templates.xml @@ -1,75 +1,168 @@ -