@ -0,0 +1,54 @@ |
|||
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg |
|||
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
Product Pack |
|||
============ |
|||
Create product pack which is a great way to raise average sales price per product, to serve customers with products that make their lives easier, and to leverage current products into new and different ones. |
|||
|
|||
Configuration |
|||
============= |
|||
- Additional configuration not required |
|||
|
|||
Installation |
|||
============ |
|||
- www.odoo.com/documentation/18.0/setup/install.html |
|||
- Install our custom addon |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
======= |
|||
General Public License, Version 3 (LGPL v3). |
|||
(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
------- |
|||
* Developer: |
|||
(V16) Jumana Jabin MP, |
|||
(V17) Gayathri V |
|||
(V18) Dhanya B |
|||
Contact: odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit https://www.cybrosys.com |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri v (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import models |
@ -0,0 +1,47 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri v (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
{ |
|||
'name': 'Product Pack', |
|||
'version': '18.0.1.0.0', |
|||
'category': 'Sales', |
|||
'summary': 'Manage Products as Pack', |
|||
'description': """Selling products in a pack is a great way to raise average |
|||
sales price per product, to serve customers with products that make their |
|||
lives easier, and to leverage current products into new and different ones. |
|||
They are profitable for smaller businesses as well as large ones.""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['sale_management', 'stock'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/product_product_views.xml', |
|||
'views/product_template_views.xml', |
|||
'views/sale_order_views.xml', |
|||
], |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'LGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,7 @@ |
|||
## Module <product_combo_pack> |
|||
|
|||
#### 08.11.2024 |
|||
#### Version 18.0.1.0.0 |
|||
#### ADD |
|||
- Initial Commit for Product Combo Pack |
|||
|
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri V (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import pack_products |
|||
from . import product_template |
|||
from . import sale_order |
@ -0,0 +1,87 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri v (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import api, fields, models, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class PackProducts(models.Model): |
|||
"""Model for selecting pack products.This model allows users to select |
|||
and manage pack products. """ |
|||
_name = 'pack.products' |
|||
_rec_name = 'product_tmpl_id' |
|||
_description = 'Select Pack Products' |
|||
|
|||
product_id = fields.Many2one('product.product', string='Product', |
|||
required=True, |
|||
domain=[('is_pack', '=', False)], |
|||
help='The specific product being referenced.') |
|||
product_tmpl_id = fields.Many2one('product.template', string='Product', |
|||
help='The template of the product.') |
|||
price = fields.Float(string='Price', compute='compute_price', store=True, |
|||
help='The calculated price of the product.') |
|||
quantity = fields.Integer(string='Quantity', default=1, |
|||
help='The quantity of the product.') |
|||
qty_available = fields.Float(string='Quantity Available', |
|||
compute='compute_quantity_of_product', |
|||
store=True, readonly=False, |
|||
help='The available quantity of the product.') |
|||
total_available_quantity = fields.Float(string='Total Quantity', |
|||
help='The total available ' |
|||
'quantity of the selected ' |
|||
'product.') |
|||
|
|||
@api.depends('product_id', 'total_available_quantity', |
|||
'product_id.qty_available') |
|||
def compute_quantity_of_product(self): |
|||
"""Compute the available quantity for each record based on the |
|||
product and location. """ |
|||
for record in self: |
|||
location_id = record.product_tmpl_id.pack_location_id |
|||
if location_id: |
|||
stock_quant = self.env['stock.quant'].search( |
|||
[('product_id', '=', record.product_id.id), |
|||
('location_id', '=', location_id.id)]) |
|||
if stock_quant: |
|||
record.qty_available = stock_quant.quantity |
|||
else: |
|||
record.qty_available = False |
|||
else: |
|||
record.qty_available = False |
|||
|
|||
@api.depends('product_id', 'quantity') |
|||
def compute_price(self): |
|||
""" Compute the price for each record based on the product and quantity. |
|||
""" |
|||
for record in self: |
|||
record.price = record.product_id.lst_price * record.quantity |
|||
|
|||
@api.onchange('quantity') |
|||
def set_price(self): |
|||
""" Update the price field when the quantity changes.""" |
|||
self.price = self.product_id.lst_price * self.quantity |
|||
|
|||
@api.constrains('quantity') |
|||
def _check_positive_qty(self): |
|||
"""Ensure that the quantity is always positive.Raises a validation |
|||
error if any of the records have a negative quantity.""" |
|||
if any([ml.quantity < 0 for ml in self]): |
|||
raise ValidationError(_('You can not enter negative quantities.')) |
@ -0,0 +1,163 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri v (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import api, fields, models, _ |
|||
from odoo.exceptions import UserError, ValidationError |
|||
|
|||
|
|||
class ProductTemplate(models.Model): |
|||
"""Model for extending the product template to include |
|||
pack-related fields.""" |
|||
_inherit = 'product.template' |
|||
|
|||
def default_pack_location(self): |
|||
""" Get the default pack location for the current company.""" |
|||
company_user = self.env.company |
|||
warehouse = self.env['stock.warehouse'].search([( |
|||
'company_id', '=', company_user.id)], limit=1) |
|||
if warehouse: |
|||
return warehouse.lot_stock_id.id |
|||
|
|||
is_pack = fields.Boolean(string='Is a Pack', help='Indicates whether the' |
|||
'product is a pack or ' |
|||
'not.') |
|||
pack_price = fields.Integer(string="Pack Price", compute='set_pack_price', |
|||
store=True, |
|||
help='The calculated price of the pack.') |
|||
pack_products_ids = fields.One2many('pack.products', 'product_tmpl_id', |
|||
string='Pack Products', copy=True, |
|||
help='The list of products included ' |
|||
'in the pack.') |
|||
pack_quantity = fields.Integer(string='Pack Quantity', |
|||
help='The quantity of the product' |
|||
' in the pack.') |
|||
pack_location_id = fields.Many2one('stock.location', |
|||
domain=[('usage', 'in', |
|||
['internal', 'transit'])], |
|||
default=default_pack_location, |
|||
string='Pack Location', |
|||
help='The default location for the pack.') |
|||
|
|||
@api.onchange('is_pack') |
|||
def _onchange_is_pack(self): |
|||
"""Method _onchange_is_pack to trigger when any change in the |
|||
field is_pack""" |
|||
if self.is_pack: |
|||
self.invoice_policy = 'delivery' |
|||
|
|||
@api.constrains('invoice_policy') |
|||
def _check_invoice_policy(self): |
|||
"""Method _check_invoice_policy to whether the product is a pack |
|||
product""" |
|||
if self.invoice_policy != 'delivery' and self.is_pack: |
|||
raise ValidationError( |
|||
_("Pack products invoicing policy should be in delivered " |
|||
"quantities")) |
|||
|
|||
@api.depends('pack_products_ids', 'pack_products_ids.price') |
|||
def set_pack_price(self): |
|||
"""Compute the pack price based on the prices of the pack products.""" |
|||
price = 0 |
|||
for record in self: |
|||
for line in record.pack_products_ids: |
|||
price = price + line.price |
|||
record.pack_price = price |
|||
|
|||
@api.model |
|||
def create(self, values): |
|||
"""Override the create method to add validation for pack products.""" |
|||
if values.get('is_pack', False): |
|||
if not values.get('pack_products_ids', []): |
|||
raise UserError(_( |
|||
'You need to add least one product in the Pack...!')) |
|||
if values.get('type', False) == 'service': |
|||
raise UserError( |
|||
_('You cannot define a pack product as a service..!')) |
|||
if values.get('invoice_policy') == 'order': |
|||
values['invoice_policy'] = 'delivery' |
|||
return super().create(values) |
|||
|
|||
def write(self, values): |
|||
"""Override the write method to add validation for pack products.""" |
|||
super().write(values) |
|||
for rec in self: |
|||
if rec.is_pack: |
|||
if not rec.pack_products_ids: |
|||
raise UserError(_( |
|||
'You need to add at least one product in the Pack...!')) |
|||
if rec.type == 'service': |
|||
raise UserError( |
|||
_('You cannot define a pack product as a service..!')) |
|||
|
|||
def update_price_product(self): |
|||
"""Update the list price of the product with the pack price.""" |
|||
self.list_price = self.pack_price |
|||
|
|||
|
|||
def get_quantity(self): |
|||
"""Calculate the pack quantity based on the availability of |
|||
pack products.""" |
|||
for pack in self: |
|||
max_packs_list = [] |
|||
for pack_product in pack.pack_products_ids: |
|||
if pack_product.quantity > 0: |
|||
max_packs = pack_product.qty_available // pack_product.quantity |
|||
max_packs_list.append(max_packs) |
|||
# # Set the max packs as the minimum value in the list |
|||
pack.pack_quantity = min(max_packs_list) if max_packs_list else 0 |
|||
|
|||
def update_quantity(self): |
|||
"""Update the pack quantity in the specified pack location.""" |
|||
company_user = self.env.company |
|||
product_id = len( |
|||
self.product_variant_ids) == 1 and self.product_variant_id.id |
|||
location_id = self.pack_location_id.id |
|||
if not location_id: |
|||
warehouse = self.env['stock.warehouse'].search([( |
|||
'company_id', '=', company_user.id)], limit=1) |
|||
location_id = warehouse.lot_stock_id.id |
|||
if not location_id: |
|||
raise UserError(_( |
|||
'You need to select the location to update the pack ' |
|||
'quantity...!')) |
|||
existing_quantity = self.env['stock.quant'].search([('product_id', '=', product_id)], limit=1) |
|||
if not existing_quantity: |
|||
self.env['stock.quant'].with_context(inventory_mode=True).sudo().create( |
|||
{ |
|||
'product_id': product_id, |
|||
'location_id': location_id, |
|||
'quantity': self.pack_quantity, |
|||
}) |
|||
else: |
|||
existing_quantity.quantity = self.pack_quantity |
|||
|
|||
@api.onchange('pack_location_id') |
|||
def change_quantity_based_on_location(self): |
|||
"""Update the total available quantity of pack products based |
|||
on the selected pack location.""" |
|||
for line in self.pack_products_ids: |
|||
stock_quant = self.env['stock.quant'].search( |
|||
[('product_id', '=', line.product_id.id), ( |
|||
'location_id', '=', self.pack_location_id.id)]) |
|||
if stock_quant: |
|||
line.total_available_quantity = stock_quant.quantity |
|||
else: |
|||
line.total_available_quantity = stock_quant.quantity |
@ -0,0 +1,118 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Gayathri v (odoo@cybrosys.com) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import api, fields, models |
|||
from odoo.fields import Command |
|||
|
|||
|
|||
class SaleOrder(models.Model): |
|||
"""Model for extending the sale order to include a selection of packs.""" |
|||
_inherit = 'sale.order' |
|||
|
|||
product_pack_ids = fields.Many2many( |
|||
'product.product', |
|||
'sale_order_product_pack_rel', |
|||
string='Select Pack', |
|||
domain=[('is_pack', '=', True)], |
|||
help='The selected pack product for the sale order.' |
|||
) |
|||
|
|||
@api.onchange('product_pack_ids') |
|||
def onchange_product_pack_ids(self): |
|||
"""Perform actions when the selected pack product changes.""" |
|||
if self.product_pack_ids: |
|||
new_order_lines = [] |
|||
for rec in self.product_pack_ids: |
|||
product_already_added = any( |
|||
line.product_id.id == rec._origin.id for line in |
|||
self.order_line) |
|||
if not product_already_added: |
|||
new_order_lines.append((0, 0, { |
|||
'product_id': rec.id, |
|||
'name': rec.name, |
|||
'product_uom_qty': 1, |
|||
'price_unit': rec.pack_price, |
|||
})) |
|||
self.order_line = new_order_lines |
|||
elif not self.product_pack_ids: |
|||
self.order_line = [(5, 0, 0)] |
|||
|
|||
def action_confirm(self): |
|||
"""Override the action_confirm method to create stock moves |
|||
for pack products.""" |
|||
super().action_confirm() |
|||
for line in self.order_line: |
|||
if line.product_id.is_pack: |
|||
for record in line.product_id.pack_products_ids: |
|||
for rec in self.picking_ids: |
|||
move = rec.move_ids.create({ |
|||
'name': record.product_id.name, |
|||
'product_id': record.product_id.id, |
|||
'product_uom_qty': record.quantity * line.product_uom_qty, |
|||
'product_uom': record.product_id.uom_id.id, |
|||
'picking_id': rec.id, |
|||
'location_id': rec.location_id.id, |
|||
'location_dest_id': rec.location_dest_id.id, |
|||
}) |
|||
move._action_confirm() |
|||
|
|||
|
|||
class SaleOrderLine(models.Model): |
|||
"""Inherit the model sale.order.line to add extra functionality and |
|||
fields""" |
|||
_inherit = 'sale.order.line' |
|||
|
|||
def _prepare_invoice_line(self, **optional_values): |
|||
"""Prepare the values to create the new invoice line for a sales order line. |
|||
|
|||
:param optional_values: any parameter that should be added to the returned invoice line |
|||
:rtype: dict |
|||
""" |
|||
self.ensure_one() |
|||
res = { |
|||
'display_type': self.display_type or 'product', |
|||
'sequence': self.sequence, |
|||
'name': self.name, |
|||
'product_id': self.product_id.id, |
|||
'product_uom_id': self.product_uom.id, |
|||
'quantity': self.qty_to_invoice, |
|||
'discount': self.discount, |
|||
'price_unit': 0 if self.product_id.is_pack == True else self.price_unit, |
|||
'tax_ids': [Command.set(self.tax_id.ids)], |
|||
'sale_line_ids': [Command.link(self.id)], |
|||
'is_downpayment': self.is_downpayment, |
|||
} |
|||
analytic_account_id = self.order_id.analytic_account_id.id |
|||
if self.analytic_distribution and not self.display_type: |
|||
res['analytic_distribution'] = self.analytic_distribution |
|||
if analytic_account_id and not self.display_type: |
|||
analytic_account_id = str(analytic_account_id) |
|||
if 'analytic_distribution' in res: |
|||
res['analytic_distribution'][analytic_account_id] = res[ |
|||
'analytic_distribution'].get( |
|||
analytic_account_id, 0) + 100 |
|||
else: |
|||
res['analytic_distribution'] = {analytic_account_id: 100} |
|||
if optional_values: |
|||
res.update(optional_values) |
|||
if self.display_type: |
|||
res['account_id'] = False |
|||
return res |
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 438 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 912 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 287 KiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 697 KiB |
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Modify product.product form view --> |
|||
<record id="product_normal_form_view" model="ir.ui.view"> |
|||
<field name="name"> |
|||
product.product.view.form.inherit.product.combo.pack |
|||
</field> |
|||
<field name="model">product.product</field> |
|||
<field name="inherit_id" ref="product.product_normal_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<!-- Add the 'is_pack' field to the 'options' div --> |
|||
<xpath expr="//div[@name='options']" position="inside"> |
|||
<div modifiers="{}"> |
|||
<field name="is_pack" modifiers="{}"/> |
|||
<label for="is_pack" modifiers="{}"/> |
|||
</div> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |