164 lines
7.6 KiB
Python
164 lines
7.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
import json
|
|
from collections import defaultdict
|
|
|
|
|
|
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.')
|
|
iface_orderline_notes = fields.Boolean(string='Internal Notes', help='Allow custom Internal notes on Orderlines.')
|
|
floor_ids = fields.Many2many('restaurant.floor', string='Restaurant Floors', help='The restaurant floors served by this point of sale.')
|
|
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.")
|
|
module_pos_restaurant = fields.Boolean(default=True)
|
|
module_pos_restaurant_appointment = fields.Boolean("Table Booking")
|
|
|
|
def get_tables_order_count_and_printing_changes(self):
|
|
self.ensure_one()
|
|
floors = self.env['restaurant.floor'].search([('pos_config_ids', '=', self.id)])
|
|
tables = self.env['restaurant.table'].search([('floor_id', 'in', floors.ids)])
|
|
domain = [('state', '=', 'draft'), ('table_id', 'in', tables.ids)]
|
|
|
|
order_stats = self.env['pos.order']._read_group(domain, ['table_id'], ['__count'])
|
|
linked_orderlines = self.env['pos.order.line'].search([('order_id.state', '=', 'draft'), ('order_id.table_id', 'in', tables.ids)])
|
|
orders_map = {table.id: count for table, count in order_stats}
|
|
changes_map = defaultdict(lambda: 0)
|
|
skip_changes_map = defaultdict(lambda: 0)
|
|
|
|
for line in linked_orderlines:
|
|
# For the moment, as this feature is not compatible with pos_self_order,
|
|
# we ignore last_order_preparation_change when it is set to false.
|
|
# In future, pos_self_order will send the various changes to the order.
|
|
if not line.order_id.last_order_preparation_change:
|
|
line.order_id.last_order_preparation_change = '{}'
|
|
|
|
last_order_preparation_change = json.loads(line.order_id.last_order_preparation_change)
|
|
prep_change = {}
|
|
for line_uuid in last_order_preparation_change:
|
|
prep_change[last_order_preparation_change[line_uuid]['line_uuid']] = last_order_preparation_change[line_uuid]
|
|
quantity_changed = 0
|
|
if line.uuid in prep_change:
|
|
quantity_changed = line.qty - prep_change[line.uuid]['quantity']
|
|
else:
|
|
quantity_changed = line.qty
|
|
|
|
if line.skip_change:
|
|
skip_changes_map[line.order_id.table_id.id] += quantity_changed
|
|
else:
|
|
changes_map[line.order_id.table_id.id] += quantity_changed
|
|
|
|
result = []
|
|
for table in tables:
|
|
result.append({'id': table.id, 'orders': orders_map.get(table.id, 0), 'changes': changes_map.get(table.id, 0), 'skip_changes': skip_changes_map.get(table.id, 0)})
|
|
return result
|
|
|
|
def _get_forbidden_change_fields(self):
|
|
forbidden_keys = super(PosConfig, self)._get_forbidden_change_fields()
|
|
forbidden_keys.append('floor_ids')
|
|
return forbidden_keys
|
|
|
|
def _set_tips_after_payment_if_country_custom(self):
|
|
self.ensure_one()
|
|
company = self.company_id or self.env.company or self.env['res.company']._get_main_company()
|
|
if company and company.country_id and company.country_id.code == 'US':
|
|
self.update({
|
|
'iface_tipproduct': True,
|
|
'set_tip_after_payment': True,
|
|
})
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
is_restaurant = 'module_pos_restaurant' not in vals or vals['module_pos_restaurant']
|
|
if is_restaurant and 'iface_splitbill' not in vals:
|
|
vals['iface_splitbill'] = True
|
|
if not is_restaurant or not vals.get('iface_tipproduct', False):
|
|
vals['set_tip_after_payment'] = False
|
|
vals["iface_orderline_notes"] = is_restaurant
|
|
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)
|
|
|
|
@api.model
|
|
def post_install_pos_localisation(self, companies=False):
|
|
self = self.sudo()
|
|
if not companies:
|
|
companies = self.env['res.company'].search([])
|
|
super(PosConfig, self).post_install_pos_localisation(companies)
|
|
for company in companies.filtered('chart_template'):
|
|
pos_configs = self.search([
|
|
*self.env['account.journal']._check_company_domain(company),
|
|
('module_pos_restaurant', '=', True),
|
|
])
|
|
if not pos_configs:
|
|
pos_configs = self.env['pos.config'].with_company(company).create({
|
|
'name': _('Bar'),
|
|
'company_id': company.id,
|
|
'module_pos_restaurant': True,
|
|
'iface_splitbill': True,
|
|
'iface_printbill': True,
|
|
'iface_orderline_notes': True,
|
|
|
|
})
|
|
pos_configs.setup_defaults(company)
|
|
|
|
def setup_defaults(self, company):
|
|
main_restaurant = self.env.ref('pos_restaurant.pos_config_main_restaurant', raise_if_not_found=False)
|
|
main_restaurant_is_present = main_restaurant and self.filtered(lambda cfg: cfg.id == main_restaurant.id)
|
|
if main_restaurant_is_present:
|
|
non_main_restaurant_configs = self - main_restaurant
|
|
non_main_restaurant_configs.assign_payment_journals(company)
|
|
main_restaurant._setup_main_restaurant_defaults()
|
|
self.generate_pos_journal(company)
|
|
self.setup_invoice_journal(company)
|
|
else:
|
|
super().setup_defaults(company)
|
|
|
|
def _setup_main_restaurant_defaults(self):
|
|
self.ensure_one()
|
|
self._set_tips_after_payment_if_country_custom()
|
|
self._link_same_non_cash_payment_methods_if_exists('point_of_sale.pos_config_main')
|
|
self._ensure_cash_payment_method('MRCSH', _('Cash Restaurant'))
|
|
self._archive_shop()
|
|
|
|
def _archive_shop(self):
|
|
shop = self.env.ref('point_of_sale.pos_config_main', raise_if_not_found=False)
|
|
if shop:
|
|
session_count = self.env['pos.session'].search_count([('config_id', '=', shop.id)])
|
|
if session_count == 0:
|
|
shop.update({'active': False})
|
|
|
|
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({
|
|
'name': '1',
|
|
'floor_id': main_floor.id,
|
|
'seats': 1,
|
|
'position_h': 100,
|
|
'position_v': 100,
|
|
'width': 100,
|
|
'height': 100,
|
|
})
|