# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ from odoo.tools import convert class PosConfig(models.Model): _inherit = 'pos.config' iface_splitbill = fields.Boolean(string='Bill Splitting', help='Enables Bill Splitting in the Point of Sale.') iface_printbill = fields.Boolean(string='Bill Printing', help='Allows to print the Bill before payment.') floor_ids = fields.Many2many('restaurant.floor', string='Restaurant Floors', help='The restaurant floors served by this point of sale.', copy=False) set_tip_after_payment = fields.Boolean('Set Tip After Payment', help="Adjust the amount authorized by payment terminals to add a tip after the customers left or at the end of the day.") default_screen = fields.Selection([('tables', 'Tables'), ('register', 'Register')], string='Default Screen', default='tables') def _get_forbidden_change_fields(self): forbidden_keys = super(PosConfig, self)._get_forbidden_change_fields() forbidden_keys.append('floor_ids') return forbidden_keys @api.model_create_multi def create(self, vals_list): for vals in vals_list: is_restaurant = 'module_pos_restaurant' in vals and vals['module_pos_restaurant'] if is_restaurant: if 'iface_printbill' not in vals: vals['iface_printbill'] = True if 'show_product_images' not in vals: vals['show_product_images'] = False if 'show_category_images' not in vals: vals['show_category_images'] = False if not is_restaurant or not vals.get('iface_tipproduct', False): vals['set_tip_after_payment'] = False pos_configs = super().create(vals_list) for config in pos_configs: if config.module_pos_restaurant: self._setup_default_floor(config) return pos_configs def write(self, vals): if ('module_pos_restaurant' in vals and vals['module_pos_restaurant'] is False): vals['floor_ids'] = [(5, 0, 0)] if ('module_pos_restaurant' in vals and not vals['module_pos_restaurant']) or ('iface_tipproduct' in vals and not vals['iface_tipproduct']): vals['set_tip_after_payment'] = False if ('module_pos_restaurant' in vals and vals['module_pos_restaurant']): self._setup_default_floor(self) return super().write(vals) def _setup_default_floor(self, pos_config): if not pos_config.floor_ids: main_floor = self.env['restaurant.floor'].create({ 'name': pos_config.company_id.name, 'pos_config_ids': [(4, pos_config.id)], }) self.env['restaurant.table'].create({ 'table_number': 1, 'floor_id': main_floor.id, 'seats': 1, 'position_h': 100, 'position_v': 100, 'width': 130, 'height': 130, }) @api.model def load_onboarding_bar_scenario(self, with_demo_data=True): journal, payment_methods_ids = self._create_journal_and_payment_methods(cash_journal_vals={'name': 'Cash Bar', 'show_on_dashboard': False}) config = self.env['pos.config'].create({ 'name': 'Bar', 'company_id': self.env.company.id, 'journal_id': journal.id, 'payment_method_ids': payment_methods_ids, 'iface_splitbill': True, 'module_pos_restaurant': True, 'default_screen': 'register' }) self.env['ir.model.data']._update_xmlids([{ 'xml_id': self._get_suffixed_ref_name('pos_restaurant.pos_config_main_bar'), 'record': config, 'noupdate': True, }]) if not self.env.ref('pos_restaurant.floor_main', raise_if_not_found=False): convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/restaurant_floor.xml', idref=None, mode='init', noupdate=True) config_floors = [(5, 0)] if (floor_main := self.env.ref('pos_restaurant.floor_main', raise_if_not_found=False)): config_floors += [(4, floor_main.id)] if (floor_patio := self.env.ref('pos_restaurant.floor_patio', raise_if_not_found=False)): config_floors += [(4, floor_patio.id)] config.update({'floor_ids': config_floors}) config._load_bar_demo_data(with_demo_data) return {'config_id': config.id} def _load_bar_demo_data(self, with_demo_data=True): self.ensure_one() convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/bar_category_data.xml', idref=None, mode='init', noupdate=True) if with_demo_data: convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/bar_demo_data.xml', idref=None, mode='init', noupdate=True) bar_categories = self.get_record_by_ref([ 'pos_restaurant.pos_category_cocktails', 'pos_restaurant.pos_category_soft_drinks', ]) if bar_categories: self.limit_categories = True self.iface_available_categ_ids = bar_categories @api.model def load_onboarding_restaurant_scenario(self, with_demo_data=True): journal, payment_methods_ids = self._create_journal_and_payment_methods(cash_journal_vals={'name': _('Cash Restaurant'), 'show_on_dashboard': False}) presets = self.get_record_by_ref([ 'pos_restaurant.pos_takein_preset', 'pos_restaurant.pos_takeout_preset', 'pos_restaurant.pos_delivery_preset', ]) + self.env['pos.preset'].search([]).ids config = self.env['pos.config'].create({ 'name': _('Restaurant'), 'company_id': self.env.company.id, 'journal_id': journal.id, 'payment_method_ids': payment_methods_ids, 'iface_splitbill': True, 'module_pos_restaurant': True, 'use_presets': bool(presets), 'default_preset_id': presets[0] if presets else False, 'available_preset_ids': [(6, 0, presets)], }) self.env['ir.model.data']._update_xmlids([{ 'xml_id': self._get_suffixed_ref_name('pos_restaurant.pos_config_main_restaurant'), 'record': config, 'noupdate': True, }]) if bool(presets): # Ensure the "Presets" menu is visible when installing the restaurant scenario self.env.ref("point_of_sale.group_pos_preset").implied_by_ids |= self.env.ref("base.group_user") if not self.env.ref('pos_restaurant.floor_main', raise_if_not_found=False): convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/restaurant_floor.xml', idref=None, mode='init', noupdate=True) config_floors = [(5, 0)] if (floor_main := self.env.ref('pos_restaurant.floor_main', raise_if_not_found=False)): config_floors += [(4, floor_main.id)] if (floor_patio := self.env.ref('pos_restaurant.floor_patio', raise_if_not_found=False)): config_floors += [(4, floor_patio.id)] config.update({'floor_ids': config_floors}) config._load_restaurant_demo_data(with_demo_data) existing_session = self.env.ref('pos_restaurant.pos_closed_session_3', raise_if_not_found=False) if with_demo_data and self.env.company.id == self.env.ref('base.main_company').id and not existing_session: convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/restaurant_demo_session.xml', idref=None, mode='init', noupdate=True) return {'config_id': config.id} @api.depends('set_tip_after_payment') def _compute_local_data_integrity(self): super()._compute_local_data_integrity() def _load_restaurant_demo_data(self, with_demo_data=True): self.ensure_one() convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/restaurant_category_data.xml', idref=None, mode='init', noupdate=True) if with_demo_data: convert.convert_file(self._env_with_clean_context(), 'pos_restaurant', 'data/scenarios/restaurant_demo_data.xml', idref=None, mode='init', noupdate=True) restaurant_categories = self.get_record_by_ref([ 'pos_restaurant.food', 'pos_restaurant.drinks', ]) if restaurant_categories: self.limit_categories = True self.iface_available_categ_ids = restaurant_categories def _get_demo_data_loader_methods(self): mapping = super()._get_demo_data_loader_methods() mapping.update({ 'pos_restaurant.pos_config_main_restaurant': self._load_restaurant_demo_data, 'pos_restaurant.pos_config_main_bar': self._load_bar_demo_data, }) return mapping def _get_default_demo_data_xml_id(self): if self.module_pos_restaurant: return 'pos_restaurant.pos_config_main_restaurant' return super()._get_default_demo_data_xml_id()