Initial commit
This commit is contained in:
5
garazd_product_label_pro/wizard/__init__.py
Normal file
5
garazd_product_label_pro/wizard/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from . import print_product_label
|
||||
from . import print_product_label_line
|
||||
from . import print_product_label_template_add
|
||||
from . import product_label_layout
|
||||
from . import print_product_label_preview
|
||||
216
garazd_product_label_pro/wizard/print_product_label.py
Normal file
216
garazd_product_label_pro/wizard/print_product_label.py
Normal file
@@ -0,0 +1,216 @@
|
||||
# Copyright © 2023 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License OPL-1 (https://www.odoo.com/documentation/15.0/legal/licenses.html).
|
||||
|
||||
from typing import List
|
||||
|
||||
from odoo import _, api, Command, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class PrintProductLabel(models.TransientModel):
|
||||
_inherit = "print.product.label"
|
||||
|
||||
report_id = fields.Many2one(
|
||||
default=lambda self: self.env.ref('garazd_product_label.action_report_product_label_from_template'),
|
||||
)
|
||||
template_id = fields.Many2one(
|
||||
comodel_name='print.product.label.template',
|
||||
# flake8: noqa: E501
|
||||
default=lambda self: self.env.user.print_label_template_id or self.env['print.product.label.template'].search([], limit=1),
|
||||
)
|
||||
allowed_template_ids = fields.Many2many(
|
||||
comodel_name='print.product.label.template',
|
||||
compute='_compute_allowed_template_ids',
|
||||
help='Technical field to restrict allowed label templates.',
|
||||
)
|
||||
allowed_template_count = fields.Integer(compute='_compute_allowed_template_ids', help='Technical field.')
|
||||
template_preview_html = fields.Html(
|
||||
compute='_compute_template_preview_html',
|
||||
compute_sudo=True,
|
||||
)
|
||||
label_template_preview = fields.Boolean(help='Show Label Template Sample.')
|
||||
pricelist_id = fields.Many2one(
|
||||
comodel_name='product.pricelist',
|
||||
)
|
||||
sale_pricelist_id = fields.Many2one(
|
||||
comodel_name='product.pricelist',
|
||||
string='Sales Pricelist',
|
||||
help='Specify this second pricelist to put one more product price to a label.',
|
||||
)
|
||||
skip_place_count = fields.Integer(
|
||||
string='Skip Places',
|
||||
default=0,
|
||||
help='Specify how many places for labels should be skipped on printing. This can'
|
||||
' be useful if you are printing on a sheet with labels already printed.',
|
||||
)
|
||||
label_type_id = fields.Many2one(
|
||||
help='You can filter label templates by selecting their type. It makes sense if you use '
|
||||
'additional extensions to print labels not for products only but for other objects as well. '
|
||||
'Like as Stock Packages, Sales Orders, Manufacturing Orders, etc. '
|
||||
'>>> To view available extensions go to the "Actions" menu and click to the "Get Label Extensions".',
|
||||
# default=lambda self: self.env.ref('garazd_product_label.type_product'),
|
||||
# required=True,
|
||||
)
|
||||
show_template_limit = fields.Integer(compute='_compute_allowed_template_ids')
|
||||
|
||||
@api.depends('label_type_id')
|
||||
def _compute_allowed_template_ids(self):
|
||||
for wizard in self:
|
||||
user_allowed_templates = self.env['print.product.label.template']._get_user_allowed_templates()
|
||||
allowed_templates = user_allowed_templates.filtered(lambda lt: lt.type_id == wizard.label_type_id)
|
||||
## Add templates without the specified type
|
||||
# if wizard.mode == 'product.product':
|
||||
# allowed_templates += user_allowed_templates.filtered(lambda lt: not lt.type_id)
|
||||
wizard.allowed_template_ids = [Command.set(allowed_templates.ids)]
|
||||
wizard.allowed_template_count = len(allowed_templates)
|
||||
# flake8: noqa: E501
|
||||
wizard.show_template_limit = self.env['ir.config_parameter'].sudo().get_param('garazd_product_label.show_label_template_limit', 7)
|
||||
|
||||
@api.depends('template_id', 'pricelist_id', 'sale_pricelist_id', 'lang')
|
||||
def _compute_template_preview_html(self):
|
||||
for wizard in self:
|
||||
products = wizard.label_ids.mapped('product_id')
|
||||
wizard.template_id.with_context(print_product_id=products[:1].id)._compute_preview_html()
|
||||
wizard.template_preview_html = wizard.with_context(**{
|
||||
'print_wizard_id': wizard.id, # It allows previewing real products on label designing
|
||||
'preview_mode': True, # It's used to avoid generating of a shorten URL
|
||||
'pricelist_id': wizard.pricelist_id.id, # It's used for previewing on label designing
|
||||
'sale_pricelist_id': wizard.sale_pricelist_id.id, # It's used for previewing on label designing
|
||||
'lang': wizard.lang or self._context.get('lang'),
|
||||
}).template_id.preview_html
|
||||
|
||||
@api.onchange('label_type_id')
|
||||
def _onchange_label_type_id(self):
|
||||
for wizard in self:
|
||||
user_template = self.env.user.print_label_template_id
|
||||
if user_template and user_template.id in wizard.allowed_template_ids.ids:
|
||||
wizard.template_id = user_template.id
|
||||
else:
|
||||
wizard.template_id = wizard.allowed_template_ids[0].id if wizard.allowed_template_ids else False
|
||||
wizard._compute_template_preview_html()
|
||||
|
||||
def _get_label_data(self):
|
||||
self.ensure_one()
|
||||
labels = self.get_labels_to_print()
|
||||
if not self.is_template_report:
|
||||
return {'ids': labels.ids, 'data': {}}
|
||||
if not self.template_id:
|
||||
raise UserError(_('Select the label template to print.'))
|
||||
self.template_id._set_paperformat()
|
||||
label_data = {
|
||||
'ids': labels.ids,
|
||||
'data': {
|
||||
'rows': self.template_id.rows,
|
||||
'cols': self.template_id.cols,
|
||||
'row_gap': self.template_id.row_gap,
|
||||
'col_gap': self.template_id.col_gap,
|
||||
'label_style':
|
||||
'overflow: hidden;'
|
||||
'font-family: "Arial";'
|
||||
'width: %(width).2fmm;'
|
||||
'height: %(height).2fmm;'
|
||||
'padding: %(padding_top).2fmm %(padding_right).2fmm'
|
||||
' %(padding_bottom).2fmm %(padding_left).2fmm;'
|
||||
'border: %(border)s;'
|
||||
'%(custom_style)s' % {
|
||||
'width': self.template_id.width,
|
||||
'height': self.template_id.height,
|
||||
'padding_top': self.template_id.padding_top,
|
||||
'padding_right': self.template_id.padding_right,
|
||||
'padding_bottom': self.template_id.padding_bottom,
|
||||
'padding_left': self.template_id.padding_left,
|
||||
'border': "%dpx solid #EEE" % self.border_width
|
||||
if self.border_width else 0,
|
||||
'custom_style': self.template_id.label_style or '',
|
||||
},
|
||||
'skip_places': self.skip_place_count,
|
||||
},
|
||||
}
|
||||
# Add extra styles for multi labels
|
||||
if self.template_id.cols != 1 or self.template_id.rows != 1:
|
||||
label_data['data']['label_style'] += 'float: left;'
|
||||
return label_data
|
||||
|
||||
def _get_report_action_params(self):
|
||||
ids, data = super(PrintProductLabel, self)._get_report_action_params()
|
||||
if self.is_template_report:
|
||||
ids = None
|
||||
data = self._get_label_data()
|
||||
return ids, data
|
||||
|
||||
@api.model
|
||||
def get_quick_report_action(
|
||||
self, model_name: str, ids: List[int], qty: int = None, template=None,
|
||||
force_direct: bool = False, close_window: bool = False,
|
||||
):
|
||||
""" Overwritten completely to use with custom label templates. """
|
||||
template = template or self.env.user.print_label_template_id
|
||||
if not template:
|
||||
raise UserError(_('Specify a label template for the current user to print custom labels.'))
|
||||
wizard = self.with_context(**{
|
||||
'active_model': model_name,
|
||||
f'default_{model_name.replace(".", "_")}_ids': ids,
|
||||
}).create({
|
||||
'report_id': self.env.ref('garazd_product_label.action_report_product_label_from_template').id,
|
||||
'template_id': template.id,
|
||||
})
|
||||
|
||||
if isinstance(qty, int):
|
||||
wizard.label_ids.write({'qty': qty, 'qty_initial': qty})
|
||||
|
||||
report_action = wizard.action_print()
|
||||
if close_window:
|
||||
report_action.update({'close_on_report_download': True})
|
||||
|
||||
return wizard.action_print_direct() if self.env.user.print_label_directly or force_direct else report_action
|
||||
|
||||
def action_add_template(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': _('Add a New Label Template'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'print.product.label.template.add',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def action_edit_template(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': self.template_id._name,
|
||||
'res_id': self.template_id.id,
|
||||
'view_mode': 'form',
|
||||
}
|
||||
|
||||
def action_reset_skip(self):
|
||||
"""Reset the skip empty places count value. """
|
||||
self.ensure_one()
|
||||
self.write({'skip_place_count': 0})
|
||||
|
||||
@api.model
|
||||
def open_extension_app_list(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': 'https://apps.odoo.com/apps/browse?repo_maintainer_id=119796&search=garazd_product_label_',
|
||||
'target': 'new',
|
||||
'target_type': 'public',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _pdf_preview(self, label_data: bytes):
|
||||
preview = self.env['print.product.label.preview'].sudo().create({'label_pdf': label_data})
|
||||
return {
|
||||
'name': _('Label Preview'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': preview._name,
|
||||
'res_id': preview.id,
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def action_pdf_preview(self):
|
||||
self.ensure_one()
|
||||
return self._pdf_preview(self.get_pdf())
|
||||
34
garazd_product_label_pro/wizard/print_product_label_line.py
Normal file
34
garazd_product_label_pro/wizard/print_product_label_line.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# Copyright © 2022 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License OPL-1 (https://www.odoo.com/documentation/15.0/legal/licenses.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PrintProductLabelLine(models.TransientModel):
|
||||
_inherit = "print.product.label.line"
|
||||
|
||||
price = fields.Float(digits='Product Price', compute='_compute_product_price')
|
||||
currency_id = fields.Many2one(comodel_name='res.currency', compute='_compute_product_price')
|
||||
promo_price = fields.Float(digits='Product Price', compute='_compute_product_price')
|
||||
promo_currency_id = fields.Many2one(comodel_name='res.currency', compute='_compute_product_price')
|
||||
|
||||
@api.depends('product_id', 'wizard_id.pricelist_id', 'wizard_id.sale_pricelist_id')
|
||||
def _compute_product_price(self):
|
||||
# When we add a new line by UI in the wizard form, the line doesn't
|
||||
# have a product. So we calculate prices only for lines with products
|
||||
with_product = self.filtered('product_id')
|
||||
for line in with_product:
|
||||
# flake8: noqa: E501
|
||||
pricelist = line.wizard_id.pricelist_id
|
||||
line.price = pricelist._get_product_price(line.product_id, 1.0) if pricelist else line.product_id.lst_price
|
||||
line.currency_id = pricelist.currency_id.id if pricelist else line.product_id.currency_id.id
|
||||
promo_pricelist = line.wizard_id.sale_pricelist_id
|
||||
line.promo_price = promo_pricelist._get_product_price(line.product_id, 1.0) if promo_pricelist else line.price
|
||||
line.promo_currency_id = promo_pricelist.currency_id.id if promo_pricelist else line.currency_id.id
|
||||
|
||||
(self - with_product).price = False
|
||||
(self - with_product).currency_id = False
|
||||
(self - with_product).promo_price = False
|
||||
(self - with_product).promo_currency_id = False
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright © 2024 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License OPL-1 (https://www.odoo.com/documentation/17.0/legal/licenses.html).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class PrintProductLabelPreview(models.TransientModel):
|
||||
_name = "print.product.label.preview"
|
||||
_description = "Preview Labels in PDF"
|
||||
|
||||
label_pdf = fields.Binary(string='PDF', readonly=True)
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="print_product_label_preview_view_form" model="ir.ui.view">
|
||||
<field name="name">print.product.label.preview.form</field>
|
||||
<field name="model">print.product.label.preview</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<field name="label_pdf" widget="pdf_viewer"/>
|
||||
<footer>
|
||||
<button special="cancel" class="oe_link" string="Close"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,115 @@
|
||||
# Copyright © 2022 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License OPL-1 (https://www.odoo.com/documentation/16.0/legal/licenses.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class PrintProductLabelTemplateAdd(models.TransientModel):
|
||||
_name = "print.product.label.template.add"
|
||||
_description = 'Wizard to add a new product label templates'
|
||||
|
||||
type_id = fields.Many2one(
|
||||
comodel_name='print.label.type',
|
||||
string='Label Type',
|
||||
default=lambda self: self.env.ref('garazd_product_label.type_product'),
|
||||
required=True,
|
||||
)
|
||||
width = fields.Integer(help='Label Width in mm.', required=True)
|
||||
height = fields.Integer(help='Label Height in mm.', required=True)
|
||||
rows = fields.Integer(default=1, required=True)
|
||||
cols = fields.Integer(default=1, required=True)
|
||||
paper_format = fields.Selection(
|
||||
selection=[
|
||||
('custom', 'Custom'),
|
||||
('A4', 'A4'),
|
||||
('Letter', 'US Letter'),
|
||||
],
|
||||
help="Select Proper Paper size",
|
||||
default='custom',
|
||||
required=True,
|
||||
)
|
||||
orientation = fields.Selection(
|
||||
selection=[
|
||||
('Portrait', 'Portrait'),
|
||||
('Landscape', 'Landscape'),
|
||||
],
|
||||
default='Portrait',
|
||||
required=True,
|
||||
)
|
||||
page_width = fields.Integer(help='Page Width in mm.')
|
||||
page_height = fields.Integer(help='Page Height in mm.')
|
||||
|
||||
@api.constrains('rows', 'cols', 'width', 'height')
|
||||
def _check_page_layout(self):
|
||||
for wizard in self:
|
||||
if not (wizard.width and wizard.height):
|
||||
raise ValidationError(_('The label sizes must be set.'))
|
||||
if not (wizard.cols and wizard.rows):
|
||||
raise ValidationError(
|
||||
_('The page layout values "Cols" and "Rows" must be set.'))
|
||||
if wizard.paper_format == 'custom' and wizard._is_multi_layout():
|
||||
if not (self.page_width or self.page_height):
|
||||
raise ValidationError(
|
||||
_('The page sizes "Page Width" and "Page Height" must be set.'))
|
||||
if self.page_width < self.width:
|
||||
raise ValidationError(
|
||||
_('The page width must be not less than label width.'))
|
||||
if self.page_height < self.height:
|
||||
raise ValidationError(
|
||||
_('The page height must be not less than label height.'))
|
||||
|
||||
def _is_multi_layout(self):
|
||||
self.ensure_one()
|
||||
return self.cols > 1 or self.rows > 1
|
||||
|
||||
def _get_label_name(self):
|
||||
self.ensure_one()
|
||||
# flake8: noqa: E501
|
||||
paperformat_name = 'Custom' if self.paper_format == 'custom' else self.paper_format
|
||||
page_sizes = f" {self.page_width}x{self.page_height} mm" if self.page_width and self.page_height else ""
|
||||
layout_name = f" ({paperformat_name}{page_sizes}: {self.cols * self.rows} pcs, {self.cols}x{self.rows})" if self.paper_format != "custom" or self._is_multi_layout() else ""
|
||||
return f'Label: {self.width}x{self.height} mm{layout_name}'
|
||||
|
||||
def _create_paperformat(self):
|
||||
self.ensure_one()
|
||||
return self.env['report.paperformat'].sudo().create({
|
||||
'name': self._get_label_name(),
|
||||
'format': self.paper_format,
|
||||
'page_width': 0 if self.paper_format != 'custom'
|
||||
else self.page_width if self._is_multi_layout()
|
||||
else self.width,
|
||||
'page_height': 0 if self.paper_format != 'custom'
|
||||
else self.page_height if self._is_multi_layout()
|
||||
else self.height,
|
||||
'orientation': self.orientation,
|
||||
'margin_top': 0,
|
||||
'margin_bottom': 0,
|
||||
'margin_left': 0,
|
||||
'margin_right': 0,
|
||||
'header_spacing': 0,
|
||||
'header_line': False,
|
||||
'disable_shrinking': True,
|
||||
'dpi': 96,
|
||||
'default': False,
|
||||
})
|
||||
|
||||
def action_create(self):
|
||||
self.ensure_one()
|
||||
template = self.env['print.product.label.template'].create({
|
||||
'type_id': self.type_id.id,
|
||||
'name': self._get_label_name().replace(':', '', 1),
|
||||
'paperformat_id': self._create_paperformat().id,
|
||||
'width': self.width,
|
||||
'height': self.height,
|
||||
'rows': self.rows,
|
||||
'cols': self.cols,
|
||||
})
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': template._name,
|
||||
'res_id': template.id,
|
||||
'view_mode': 'form',
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="print_product_label_template_add_view_form" model="ir.ui.view">
|
||||
<field name="name">print.product.label.template.add.view.form</field>
|
||||
<field name="model">print.product.label.template.add</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="type_id" widget="selection_badge"/>
|
||||
</group>
|
||||
<group>
|
||||
<separator string="Label" colspan="2"/>
|
||||
<group>
|
||||
<label for="width"/>
|
||||
<div class="o_row"><field name="width" string="Width"/><span class="text-muted"> mm</span></div>
|
||||
</group>
|
||||
<group>
|
||||
<label for="height"/>
|
||||
<div class="o_row"><field name="height" string="Height"/><span class="text-muted"> mm</span></div>
|
||||
</group>
|
||||
<separator string="Layout" colspan="2"/>
|
||||
<group>
|
||||
<field name="cols" title="Cols"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="rows" title="Rows"/>
|
||||
</group>
|
||||
<separator string="Page" colspan="2"/>
|
||||
<group>
|
||||
<field name="paper_format" widget="radio" options="{'horizontal': true}"/>
|
||||
<field name="page_width"
|
||||
string="Page Width"
|
||||
invisible="paper_format != 'custom' or cols == 1 and rows == 1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="orientation" widget="radio" options="{'horizontal': true}"/>
|
||||
<field name="page_height"
|
||||
string="Page Height"
|
||||
invisible="paper_format != 'custom' or cols == 1 and rows == 1"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="action_create"
|
||||
string="Create Template"
|
||||
type="object"
|
||||
icon="fa-plus"
|
||||
class="btn-primary"/>
|
||||
<button special="cancel" class="oe_link" string="Close"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="action_product_label_template_list" model="ir.actions.act_window">
|
||||
<field name="name">Label Templates</field>
|
||||
<field name="res_model">print.product.label.template</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="context">{'active_test': False}</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="label_templates_menu"
|
||||
name="Label Templates"
|
||||
parent="base.reporting_menuitem"
|
||||
action="action_product_label_template_list"
|
||||
sequence="10"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
<record id="print_product_label_view_form" model="ir.ui.view">
|
||||
<field name="name">print.product.label.view.form.inherit.garazd_product_label_pro</field>
|
||||
<field name="model">print.product.label</field>
|
||||
<field name="inherit_id" ref="garazd_product_label.print_product_label_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='label_type_id']" position="before">
|
||||
<button name="action_pdf_preview" type="object" string="PDF Preview" icon="fa-file-pdf-o" class="border btn-light mr8"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='label_type_id']" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='output']" position="after">
|
||||
<field name="label_template_preview" string="Show Label" widget="boolean_toggle" invisible="not is_template_report"/>
|
||||
</xpath>
|
||||
<xpath expr="//group[@name='label_report']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//a[@name='label_builder_link']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//group[@name='label_template']" position="inside">
|
||||
<div class="o_row" colspan="2">
|
||||
<field name="show_template_limit" invisible="1"/>
|
||||
<field name="allowed_template_ids" invisible="1"/>
|
||||
<field name="allowed_template_count" invisible="1"/>
|
||||
<field name="template_id"
|
||||
domain="[('id', 'in', allowed_template_ids)]"
|
||||
required="is_template_report"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
/>
|
||||
<button name="action_edit_template"
|
||||
title="Edit Template"
|
||||
type="object"
|
||||
icon="fa-external-link"
|
||||
context="{'print_wizard_id': id}"
|
||||
invisible="not template_id"/>
|
||||
<button name="action_add_template"
|
||||
string="Add"
|
||||
type="object"
|
||||
icon="fa-plus"
|
||||
class="btn-primary"
|
||||
title="Create a new label template"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//group[@name='label_template']" position="after">
|
||||
<group col="2" colspan="2">
|
||||
<div class="o_row" colspan="2" nolabel="1">
|
||||
<field name="template_preview_html" invisible="not label_template_preview"/>
|
||||
</div>
|
||||
</group>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='action_restore_initial_qty']" position="after">
|
||||
<span class="text-muted px-3">|</span>
|
||||
<span class="oe_form_field pr-2">Skip:</span>
|
||||
<field name="skip_place_count" class="mr-2" style="width: 40px !important; text-align: right;"/>
|
||||
<button name="action_reset_skip"
|
||||
title="Reset the value of skipping empty places."
|
||||
type="object"
|
||||
class="btn-xs btn-light"
|
||||
icon="fa-remove"/>
|
||||
<span class="text-muted px-3">|</span>
|
||||
<field name="pricelist_id" class="mr8" options="{'no_open': True, 'no_create': True}" placeholder="Select a pricelist..."/>
|
||||
</xpath>
|
||||
<xpath expr="//list/field[@name='barcode']" position="after">
|
||||
<field name="price" optional="show"/>
|
||||
<field name="currency_id" optional="show"/>
|
||||
<field name="promo_price" optional="hide"/>
|
||||
<field name="promo_currency_id" string="Currency" optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='options']//field[@name='company_id']" position="after">
|
||||
<field name="sale_pricelist_id" options="{'no_create': True}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
62
garazd_product_label_pro/wizard/product_label_layout.py
Normal file
62
garazd_product_label_pro/wizard/product_label_layout.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright © 2024 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License OPL-1 (https://www.odoo.com/documentation/16.0/legal/licenses.html).
|
||||
|
||||
from odoo import _, api, Command, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class ProductLabelLayout(models.TransientModel):
|
||||
_inherit = 'product.label.layout'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
# flake8: noqa: E501
|
||||
default_vals = super(ProductLabelLayout, self).default_get(fields_list)
|
||||
if 'garazd_label_template_id' not in default_vals:
|
||||
default_vals['garazd_label_template_id'] = self.env.user.print_label_template_id.id
|
||||
default_vals['garazd_allowed_template_ids'] = [Command.set(self.env['print.product.label.template']._get_user_allowed_templates().ids)]
|
||||
return default_vals
|
||||
|
||||
use_alternative_template = fields.Boolean(string='Custom Templates')
|
||||
garazd_label_template_id = fields.Many2one(
|
||||
comodel_name='print.product.label.template',
|
||||
string='Label Template',
|
||||
)
|
||||
garazd_allowed_template_ids = fields.Many2many(
|
||||
comodel_name='print.product.label.template',
|
||||
compute='_compute_garazd_allowed_template_ids',
|
||||
string='Allowed Templates',
|
||||
help='Technical field to restrict allowed for the current user templates.',
|
||||
)
|
||||
garazd_allowed_template_count = fields.Integer(compute='_compute_garazd_allowed_template_ids')
|
||||
garazd_show_template_limit = fields.Integer(compute='_compute_garazd_allowed_template_ids')
|
||||
|
||||
@api.depends_context('uid')
|
||||
@api.depends('use_alternative_template')
|
||||
def _compute_garazd_allowed_template_ids(self):
|
||||
allowed_templates = self.env['print.product.label.template']._get_user_allowed_templates()
|
||||
self.garazd_allowed_template_ids = [Command.set(allowed_templates.ids)]
|
||||
self.garazd_allowed_template_count = len(allowed_templates)
|
||||
# flake8: noqa: E501
|
||||
self.garazd_show_template_limit = self.env['ir.config_parameter'].sudo().get_param('garazd_product_label.show_label_template_limit', 7)
|
||||
|
||||
def process(self):
|
||||
self.ensure_one()
|
||||
if not self.use_alternative_template:
|
||||
return super(ProductLabelLayout, self).process()
|
||||
|
||||
if not self.garazd_label_template_id:
|
||||
raise UserError(_("Please specify a custom label template."))
|
||||
if not (self.product_tmpl_ids or self.product_ids):
|
||||
# flake8: noqa: E501
|
||||
raise UserError(_("No product to print, if the product is archived please unarchive it before printing its label."))
|
||||
|
||||
return self.env['print.product.label'].get_quick_report_action(
|
||||
model_name='product.template' if self.product_tmpl_ids else 'product.product',
|
||||
ids=self.product_tmpl_ids.ids if self.product_tmpl_ids else self.product_ids.ids,
|
||||
qty=self.custom_quantity,
|
||||
template=self.garazd_label_template_id,
|
||||
close_window=True,
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="product_label_layout_form" model="ir.ui.view">
|
||||
<field name="name">product.label.layout.form.inherit.garazd_product_label_pro</field>
|
||||
<field name="model">product.label.layout</field>
|
||||
<field name="inherit_id" ref="product.product_label_layout_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='print_format']" position="before">
|
||||
<field name="use_alternative_template" widget="boolean_toggle"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='print_format']" position="attributes">
|
||||
<attribute name="invisible">use_alternative_template</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='print_format']" position="after">
|
||||
<field name="garazd_allowed_template_ids" invisible="1"/> <!-- Technical field -->
|
||||
<field name="garazd_allowed_template_count" invisible="1"/> <!-- Technical field -->
|
||||
<field name="garazd_show_template_limit" invisible="1"/> <!-- Technical field -->
|
||||
<field name="garazd_label_template_id"
|
||||
domain="[('id', 'in', garazd_allowed_template_ids)]"
|
||||
options="{'no_create': True}"
|
||||
invisible="not use_alternative_template or use_alternative_template and garazd_allowed_template_count <= garazd_show_template_limit"
|
||||
required="use_alternative_template and garazd_allowed_template_count > garazd_show_template_limit"/>
|
||||
<field name="garazd_label_template_id"
|
||||
domain="[('id', 'in', garazd_allowed_template_ids)]"
|
||||
options="{'no_create': True}"
|
||||
invisible="not use_alternative_template or use_alternative_template and garazd_allowed_template_count > garazd_show_template_limit"
|
||||
required="use_alternative_template and garazd_allowed_template_count <= garazd_show_template_limit"
|
||||
widget="radio"
|
||||
/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user