140 lines
6.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from itertools import groupby
from operator import itemgetter
from datetime import date
class ProductTemplate(models.Model):
_inherit = 'product.template'
available_in_pos = fields.Boolean(string='Available in POS', help='Check if you want this product to appear in the Point of Sale.', default=False)
to_weight = fields.Boolean(string='To Weigh With Scale', help="Check if the product should be weighted using the hardware scale integration.")
pos_categ_ids = fields.Many2many(
'pos.category', string='Point of Sale Category',
help="Category used in the Point of Sale.")
combo_ids = fields.Many2many('pos.combo', string='Combinations')
detailed_type = fields.Selection(selection_add=[
('combo', 'Combo')
], ondelete={'combo': 'set consu'})
type = fields.Selection(selection_add=[
('combo', 'Combo')
], ondelete={'combo': 'set consu'})
@api.ondelete(at_uninstall=False)
def _unlink_except_open_session(self):
product_ctx = dict(self.env.context or {}, active_test=False)
if self.with_context(product_ctx).search_count([('id', 'in', self.ids), ('available_in_pos', '=', True)]):
if self.env['pos.session'].sudo().search_count([('state', '!=', 'closed')]):
raise UserError(_("To delete a product, make sure all point of sale sessions are closed.\n\n"
"Deleting a product available in a session would be like attempting to snatch a"
"hamburger from a customers hand mid-bite; chaos will ensue as ketchup and mayo go flying everywhere!"))
@api.onchange('sale_ok')
def _onchange_sale_ok(self):
if not self.sale_ok:
self.available_in_pos = False
@api.constrains('available_in_pos')
def _check_combo_inclusions(self):
for product in self:
if not product.available_in_pos:
combo_name = self.env['pos.combo.line'].search([('product_id', 'in', product.product_variant_ids.ids)], limit=1).combo_id.name
if combo_name:
raise UserError(_('You must first remove this product from the %s combo', combo_name))
class ProductProduct(models.Model):
_inherit = 'product.product'
@api.ondelete(at_uninstall=False)
def _unlink_except_active_pos_session(self):
product_ctx = dict(self.env.context or {}, active_test=False)
if self.env['pos.session'].sudo().search_count([('state', '!=', 'closed')]):
if self.with_context(product_ctx).search_count([('id', 'in', self.ids), ('product_tmpl_id.available_in_pos', '=', True)]):
raise UserError(_("To delete a product, make sure all point of sale sessions are closed.\n\n"
"Deleting a product available in a session would be like attempting to snatch a"
"hamburger from a customers hand mid-bite; chaos will ensue as ketchup and mayo go flying everywhere!"))
def get_product_info_pos(self, price, quantity, pos_config_id):
self.ensure_one()
config = self.env['pos.config'].browse(pos_config_id)
# Tax related
taxes = self.taxes_id.compute_all(price, config.currency_id, quantity, self)
grouped_taxes = {}
for tax in taxes['taxes']:
if tax['id'] in grouped_taxes:
grouped_taxes[tax['id']]['amount'] += tax['amount']/quantity if quantity else 0
else:
grouped_taxes[tax['id']] = {
'name': tax['name'],
'amount': tax['amount']/quantity if quantity else 0
}
all_prices = {
'price_without_tax': taxes['total_excluded']/quantity if quantity else 0,
'price_with_tax': taxes['total_included']/quantity if quantity else 0,
'tax_details': list(grouped_taxes.values()),
}
# Pricelists
if config.use_pricelist:
pricelists = config.available_pricelist_ids
else:
pricelists = config.pricelist_id
price_per_pricelist_id = pricelists._price_get(self, quantity) if pricelists else False
pricelist_list = [{'name': pl.name, 'price': price_per_pricelist_id[pl.id]} for pl in pricelists]
# Warehouses
warehouse_list = [
{'name': w.name,
'available_quantity': self.with_context({'warehouse': w.id}).qty_available,
'forecasted_quantity': self.with_context({'warehouse': w.id}).virtual_available,
'uom': self.uom_name}
for w in self.env['stock.warehouse'].search([])]
# Suppliers
key = itemgetter('partner_id')
supplier_list = []
for key, group in groupby(sorted(self.seller_ids, key=key), key=key):
for s in list(group):
if not((s.date_start and s.date_start > date.today()) or (s.date_end and s.date_end < date.today()) or (s.min_qty > quantity)):
supplier_list.append({
'name': s.partner_id.name,
'delay': s.delay,
'price': s.price
})
break
# Variants
variant_list = [{'name': attribute_line.attribute_id.name,
'values': list(map(lambda attr_name: {'name': attr_name, 'search': '%s %s' % (self.name, attr_name)}, attribute_line.value_ids.mapped('name')))}
for attribute_line in self.attribute_line_ids]
return {
'all_prices': all_prices,
'pricelists': pricelist_list,
'warehouses': warehouse_list,
'suppliers': supplier_list,
'variants': variant_list
}
class ProductAttributeCustomValue(models.Model):
_inherit = "product.attribute.custom.value"
pos_order_line_id = fields.Many2one('pos.order.line', string="PoS Order Line", ondelete='cascade')
class UomCateg(models.Model):
_inherit = 'uom.category'
is_pos_groupable = fields.Boolean(string='Group Products in POS',
help="Check if you want to group products of this category in point of sale orders")
class Uom(models.Model):
_inherit = 'uom.uom'
is_pos_groupable = fields.Boolean(related='category_id.is_pos_groupable', readonly=False)