diff options
Diffstat (limited to 'addons/website_sale_stock/models')
| -rw-r--r-- | addons/website_sale_stock/models/__init__.py | 9 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/product_product.py | 20 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/product_template.py | 54 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/res_config_settings.py | 36 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/sale_order.py | 61 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/stock_picking.py | 14 | ||||
| -rw-r--r-- | addons/website_sale_stock/models/website.py | 22 |
7 files changed, 216 insertions, 0 deletions
diff --git a/addons/website_sale_stock/models/__init__.py b/addons/website_sale_stock/models/__init__.py new file mode 100644 index 00000000..ee736ece --- /dev/null +++ b/addons/website_sale_stock/models/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import website +from . import product_product +from . import product_template +from . import res_config_settings +from . import sale_order +from . import stock_picking diff --git a/addons/website_sale_stock/models/product_product.py b/addons/website_sale_stock/models/product_product.py new file mode 100644 index 00000000..8c33b40d --- /dev/null +++ b/addons/website_sale_stock/models/product_product.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models +from odoo.addons.website.models import ir_http + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + cart_qty = fields.Integer(compute='_compute_cart_qty') + + def _compute_cart_qty(self): + website = ir_http.get_request_website() + if not website: + self.cart_qty = 0 + return + cart = website.sale_get_order() + for product in self: + product.cart_qty = sum(cart.order_line.filtered(lambda p: p.product_id.id == product.id).mapped('product_uom_qty')) if cart else 0 diff --git a/addons/website_sale_stock/models/product_template.py b/addons/website_sale_stock/models/product_template.py new file mode 100644 index 00000000..3a3e2067 --- /dev/null +++ b/addons/website_sale_stock/models/product_template.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + inventory_availability = fields.Selection([ + ('never', 'Sell regardless of inventory'), + ('always', 'Show inventory on website and prevent sales if not enough stock'), + ('threshold', 'Show inventory below a threshold and prevent sales if not enough stock'), + ('custom', 'Show product-specific notifications'), + ], string='Inventory Availability', help='Adds an inventory availability status on the web product page.', default='never') + available_threshold = fields.Float(string='Availability Threshold', default=5.0) + custom_message = fields.Text(string='Custom Message', default='', translate=True) + + def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False, only_template=False): + combination_info = super(ProductTemplate, self)._get_combination_info( + combination=combination, product_id=product_id, add_qty=add_qty, pricelist=pricelist, + parent_combination=parent_combination, only_template=only_template) + + if not self.env.context.get('website_sale_stock_get_quantity'): + return combination_info + + if combination_info['product_id']: + product = self.env['product.product'].sudo().browse(combination_info['product_id']) + website = self.env['website'].get_current_website() + virtual_available = product.with_context(warehouse=website.warehouse_id.id).virtual_available + combination_info.update({ + 'virtual_available': virtual_available, + 'virtual_available_formatted': self.env['ir.qweb.field.float'].value_to_html(virtual_available, {'precision': 0}), + 'product_type': product.type, + 'inventory_availability': product.inventory_availability, + 'available_threshold': product.available_threshold, + 'custom_message': product.custom_message, + 'product_template': product.product_tmpl_id.id, + 'cart_qty': product.cart_qty, + 'uom_name': product.uom_id.name, + }) + else: + product_template = self.sudo() + combination_info.update({ + 'virtual_available': 0, + 'product_type': product_template.type, + 'inventory_availability': product_template.inventory_availability, + 'available_threshold': product_template.available_threshold, + 'custom_message': product_template.custom_message, + 'product_template': product_template.id, + 'cart_qty': 0 + }) + + return combination_info diff --git a/addons/website_sale_stock/models/res_config_settings.py b/addons/website_sale_stock/models/res_config_settings.py new file mode 100644 index 00000000..17fcafc8 --- /dev/null +++ b/addons/website_sale_stock/models/res_config_settings.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + inventory_availability = fields.Selection([ + ('never', 'Sell regardless of inventory'), + ('always', 'Show inventory on website and prevent sales if not enough stock'), + ('threshold', 'Show inventory when below the threshold and prevent sales if not enough stock'), + ('custom', 'Show product-specific notifications'), + ], string='Inventory Availability', default='never') + available_threshold = fields.Float(string='Availability Threshold') + website_warehouse_id = fields.Many2one('stock.warehouse', related='website_id.warehouse_id', domain="[('company_id', '=', website_company_id)]", readonly=False) + + def set_values(self): + super(ResConfigSettings, self).set_values() + IrDefault = self.env['ir.default'].sudo() + IrDefault.set('product.template', 'inventory_availability', self.inventory_availability) + IrDefault.set('product.template', 'available_threshold', self.available_threshold if self.inventory_availability == 'threshold' else None) + + @api.model + def get_values(self): + res = super(ResConfigSettings, self).get_values() + IrDefault = self.env['ir.default'].sudo() + res.update(inventory_availability=IrDefault.get('product.template', 'inventory_availability') or 'never', + available_threshold=IrDefault.get('product.template', 'available_threshold') or 5.0) + return res + + @api.onchange('website_company_id') + def _onchange_website_company_id(self): + if self.website_warehouse_id.company_id != self.website_company_id: + return {'value': {'website_warehouse_id': False}} diff --git a/addons/website_sale_stock/models/sale_order.py b/addons/website_sale_stock/models/sale_order.py new file mode 100644 index 00000000..169f97cb --- /dev/null +++ b/addons/website_sale_stock/models/sale_order.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, api, fields +from odoo.tools.translate import _ + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + warning_stock = fields.Char('Warning') + + def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs): + values = super(SaleOrder, self)._cart_update(product_id, line_id, add_qty, set_qty, **kwargs) + line_id = values.get('line_id') + + for line in self.order_line: + if line.product_id.type == 'product' and line.product_id.inventory_availability in ['always', 'threshold']: + cart_qty = sum(self.order_line.filtered(lambda p: p.product_id.id == line.product_id.id).mapped('product_uom_qty')) + # The quantity should be computed based on the warehouse of the website, not the + # warehouse of the SO. + website = self.env['website'].get_current_website() + if cart_qty > line.product_id.with_context(warehouse=website.warehouse_id.id).virtual_available and (line_id == line.id): + qty = line.product_id.with_context(warehouse=website.warehouse_id.id).virtual_available - cart_qty + new_val = super(SaleOrder, self)._cart_update(line.product_id.id, line.id, qty, 0, **kwargs) + values.update(new_val) + + # Make sure line still exists, it may have been deleted in super()_cartupdate because qty can be <= 0 + if line.exists() and new_val['quantity']: + line.warning_stock = _('You ask for %s products but only %s is available') % (cart_qty, new_val['quantity']) + values['warning'] = line.warning_stock + else: + self.warning_stock = _("Some products became unavailable and your cart has been updated. We're sorry for the inconvenience.") + values['warning'] = self.warning_stock + return values + + def _website_product_id_change(self, order_id, product_id, qty=0): + res = super(SaleOrder, self)._website_product_id_change(order_id, product_id, qty=qty) + product = self.env['product.product'].browse(product_id) + res['customer_lead'] = product.sale_delay + return res + + def _get_stock_warning(self, clear=True): + self.ensure_one() + warn = self.warning_stock + if clear: + self.warning_stock = '' + return warn + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + warning_stock = fields.Char('Warning') + + def _get_stock_warning(self, clear=True): + self.ensure_one() + warn = self.warning_stock + if clear: + self.warning_stock = '' + return warn diff --git a/addons/website_sale_stock/models/stock_picking.py b/addons/website_sale_stock/models/stock_picking.py new file mode 100644 index 00000000..279190d4 --- /dev/null +++ b/addons/website_sale_stock/models/stock_picking.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, api, fields +from odoo.tools.translate import _ + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + website_id = fields.Many2one('website', related='sale_id.website_id', string='Website', + help='Website this picking belongs to.', + store=True, readonly=True) + diff --git a/addons/website_sale_stock/models/website.py b/addons/website_sale_stock/models/website.py new file mode 100644 index 00000000..78d2301c --- /dev/null +++ b/addons/website_sale_stock/models/website.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models + + +class Website(models.Model): + _inherit = 'website' + + warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse') + + def _prepare_sale_order_values(self, partner, pricelist): + self.ensure_one() + values = super(Website, self)._prepare_sale_order_values(partner, pricelist) + if values['company_id']: + warehouse_id = ( + self.warehouse_id and self.warehouse_id.id or + self.env['ir.default'].get('sale.order', 'warehouse_id', company_id=values.get('company_id')) or + self.env['ir.default'].get('sale.order', 'warehouse_id') or + self.env['stock.warehouse'].sudo().search([('company_id', '=', values['company_id'])], limit=1).id + ) + if warehouse_id: + values['warehouse_id'] = warehouse_id + return values |
