summaryrefslogtreecommitdiff
path: root/addons/website_sale_stock/models
diff options
context:
space:
mode:
Diffstat (limited to 'addons/website_sale_stock/models')
-rw-r--r--addons/website_sale_stock/models/__init__.py9
-rw-r--r--addons/website_sale_stock/models/product_product.py20
-rw-r--r--addons/website_sale_stock/models/product_template.py54
-rw-r--r--addons/website_sale_stock/models/res_config_settings.py36
-rw-r--r--addons/website_sale_stock/models/sale_order.py61
-rw-r--r--addons/website_sale_stock/models/stock_picking.py14
-rw-r--r--addons/website_sale_stock/models/website.py22
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