Permalink
Browse files

[IMP] lunch: reintroduce lunch_alerts, change display of wizard

We want to be able to use alerts in order to display a message to the
users.
We want to have a minimal display in the wizard.
We want to link the toppings to the categories instead of the suppliers.

closes #29301
  • Loading branch information...
RomainLibert committed Dec 5, 2018
1 parent 1da63f0 commit 6f5dc5733fa387a410166afb24339bb2a4a88019
@@ -28,6 +28,7 @@
'report/lunch_order_templates.xml',
'views/lunch_templates.xml',
'wizard/lunch_line_wizard_views.xml',
'views/lunch_alert_views.xml',
'views/lunch_cashmove_views.xml',
'views/lunch_orders_views.xml',
'views/lunch_product_views.xml',
@@ -17,6 +17,7 @@ def infos(self, user_id=None):
'userimage': '/web/image?model=res.users&id=%s&field=image_small' % user.id,
'is_manager': request.env.user.has_group('lunch.group_lunch_manager'),
'users': request.env['res.users'].search_read([('groups_id', 'not in', [request.env.ref('base.group_portal').id])], ['name']),
'alerts': request.env['lunch.alert'].search_read([('available_today', '=', True)], ['message'])
}
order = self._get_current_order(user.id)
@@ -285,11 +285,15 @@
<field name="image" type="base64" file="lunch/static/img/napoli.png"/>
</record>
<record model="lunch.product" id="product_olives">
<record model="lunch.topping.type" id="type_garniture">
<field name="name">Garniture</field>
</record>
<record model="lunch.topping" id="product_olives">
<field name="name">Olives</field>
<field name="price">0.30</field>
<field name="supplier_id" eval="str(ref('supplier_pizza_inn'))"/>
<field name="is_topping" eval="True"/>
<field name="category_id" ref="categ_pizza"/>
<field name="type_id" ref="type_garniture"/>
</record>
<record model="lunch.product" id="product_4formaggi">
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from . import lunch_alert
from . import lunch_cashmove
from . import lunch_order
from . import lunch_product
@@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import math
import pytz
from datetime import datetime, time
from odoo import api, fields, models
from odoo.osv import expression
from odoo.tools import float_round
WEEKDAY_TO_NAME = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
def float_to_time(hours, tz=None):
""" Convert a number of hours into a time object. """
if hours == 24.0:
return time.max
fractional, integral = math.modf(hours)
res = time(int(integral), int(float_round(60 * fractional, precision_digits=0)), 0)
if tz:
res = res.replace(tzinfo=pytz.timezone(tz))
return res
def time_to_float(t):
return float_round(t.hour + t.minute/60 + t.second/3600, precision_digits=2)
class LunchAlert(models.Model):
""" Alerts to display during a lunch order. An alert can be specific to a
given day, weekly or daily. The alert is displayed from start to end hour. """
_name = 'lunch.alert'
_description = 'Lunch Alert'
_rec_name = 'message'
message = fields.Text('Message', required=True)
recurrency = fields.Selection([('once', 'Specific Day'), ('reccurent', 'Reccurent')], 'Recurrency', default='once')
recurrency_from = fields.Float('From', default=7)
recurrency_to = fields.Float('To', default=23)
recurrency_date = fields.Date('Day', default=fields.Date.today())
recurrency_date_from = fields.Datetime('from', compute='_compute_recurrency_date_from', store=True)
recurrency_date_to = fields.Datetime('to', compute='_compute_recurrency_date_to', store=True)
recurrency_monday = fields.Boolean('Monday')
recurrency_tuesday = fields.Boolean('Tuesday')
recurrency_wednesday = fields.Boolean('Wednesday')
recurrency_thursday = fields.Boolean('Thursday')
recurrency_friday = fields.Boolean('Friday')
recurrency_saturday = fields.Boolean('Saturday')
recurrency_sunday = fields.Boolean('Sunday')
available_today = fields.Boolean('This is True when if the supplier is available today',
compute='_compute_available_today', search='_search_available_today')
@api.depends('recurrency_date', 'recurrency_from')
def _compute_recurrency_date_from(self):
for alert in self:
if alert.recurrency_date and alert.recurrency_from:
alert.recurrency_date_from = datetime.combine(alert.recurrency_date, float_to_time(alert.recurrency_from))
@api.depends('recurrency_date', 'recurrency_to')
def _compute_recurrency_date_to(self):
for alert in self:
if alert.recurrency_date and alert.recurrency_to:
alert.recurrency_date_to = datetime.combine(alert.recurrency_date, float_to_time(alert.recurrency_to))
@api.depends('recurrency', 'recurrency_date', 'recurrency_from', 'recurrency_to', 'recurrency_monday',
'recurrency_tuesday', 'recurrency_wednesday', 'recurrency_thursday',
'recurrency_friday', 'recurrency_saturday', 'recurrency_sunday')
def _compute_available_today(self):
now = fields.Datetime.now()
for alert in self:
time_from = float_to_time(alert.recurrency_from)
time_to = float_to_time(alert.recurrency_to)
if alert.recurrency == 'once':
alert.available_today = (alert.recurrency_date_from <= now <= alert.recurrency_date_to)
else:
fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[now.weekday()])
alert.available_today = alert[fieldname] and (time_from <= now.time() <= time_to)
def _search_available_today(self, operator, value):
if (not operator in ['=', '!=']) or (not value in [True, False]):
return []
searching_for_true = (operator == '=' and value) or (operator == '!=' and not value)
now = fields.Datetime.now()
float_now = time_to_float(now.time())
fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[now.weekday()])
if searching_for_true:
specific = expression.AND([
[('recurrency', '=', 'once')],
[('recurrency_date_from', '<=', now)],
[('recurrency_date_to', '>=', now)]
])
else:
specific = expression.AND([
[('recurrency', '=', 'once')],
expression.OR([
[('recurrency_date_from', '>=', now)],
[('recurrency_date_to', '<=', now)]
])
])
recurrence = expression.AND([
[(fieldname, operator, value)],
[('recurrency_from', '<=' if searching_for_true else '>=', float_now)],
[('recurrency_to', '>=' if searching_for_true else '<=', float_now)]
])
return expression.OR([specific, recurrence])
@@ -123,8 +123,8 @@ class LunchOrderLine(models.Model):
name = fields.Char(related='product_id.name', string="Product Name", readonly=True)
order_id = fields.Many2one('lunch.order', 'Order', ondelete='cascade', required=True)
topping_ids = fields.Many2many('lunch.product', string='Toppings')
product_id = fields.Many2one('lunch.product', string="Product", domain=[('is_topping', '=', False)], required=True)
topping_ids = fields.Many2many('lunch.topping', string='Toppings')
product_id = fields.Many2one('lunch.product', string="Product", required=True)
category_id = fields.Many2one('lunch.product.category', string='Product Category',
related='product_id.category_id', readonly=True, store=True)
date = fields.Date(string='Date', related='order_id.date', readonly=True, store=True)
@@ -147,7 +147,7 @@ class LunchOrderLine(models.Model):
@api.depends('topping_ids', 'product_id', 'quantity')
def _compute_total_price(self):
for line in self:
line.price = line.quantity * sum(product.price for product in line.product_id | line.topping_ids)
line.price = line.quantity * (line.product_id.price + sum(line.topping_ids.mapped('price')))
def update_quantity(self, increment):
for line in self:
@@ -14,6 +14,37 @@ class LunchProductCategory(models.Model):
_description = 'Lunch Product Category'
name = fields.Char('Product Category', required=True)
topping_ids = fields.One2many('lunch.topping', 'category_id')
class LunchToppingType(models.Model):
""""""
_name = 'lunch.topping.type'
_description = 'Lunch Topping Type'
name = fields.Char('Name', required=True)
class LunchTopping(models.Model):
""""""
_name = 'lunch.topping'
_description = 'Lunch Toppings'
name = fields.Char('Name', required=True)
price = fields.Float('Price', digits=dp.get_precision('Account'), required=True)
category_id = fields.Many2one('lunch.product.category')
type_id = fields.Many2one('lunch.topping.type')
def name_get(self):
currency_id = self.env.user.company_id.currency_id
res = dict(super(LunchTopping, self).name_get())
for topping in self:
if currency_id.position == 'before':
price = '%s %s' % (currency_id.symbol, topping.price)
else:
price = '%s %s' % (topping.price, currency_id.symbol)
res[topping.id] = '%s %s' % (topping.name, price)
return list(res.items())
class LunchProduct(models.Model):
@@ -22,12 +53,11 @@ class LunchProduct(models.Model):
_description = 'Lunch Product'
name = fields.Char('Name', required=True)
category_id = fields.Many2one('lunch.product.category', 'Product Category')
category_id = fields.Many2one('lunch.product.category', 'Product Category', required=True)
description = fields.Text('Description')
price = fields.Float('Price', digits=dp.get_precision('Account'), required=True)
supplier_id = fields.Many2one('lunch.supplier', 'Vendor', required=True)
active = fields.Boolean(default=True)
is_topping = fields.Boolean("This product is an extra garniture")
# image: all image fields are base64 encoded and PIL-supported
image = fields.Binary(
@@ -49,6 +49,9 @@ class LunchSupplier(models.Model):
vat = fields.Char(related='partner_id.vat')
responsible_id = fields.Many2one('res.users', string="Responsible", domain=lambda self: [('groups_id', 'in', self.env.ref('lunch.group_lunch_manager').id)],
help="This is used to set a responsible for this particular vendor")
image = fields.Binary(related='partner_id.image', readonly=False)
image_medium = fields.Binary(related='partner_id.image_medium', readonly=False)
image_small = fields.Binary(related='partner_id.image_small', readonly=False)
@@ -60,17 +63,17 @@ class LunchSupplier(models.Model):
automatic_email_send = fields.Boolean('Automatic Email Sending')
automatic_email_time = fields.Float('Hour')
recurrency = fields.Selection([('once', 'Specific Day'), ('reccurent', 'Reccurent')], 'Recurrency', default='once')
recurrency_from = fields.Float('From')
recurrency_to = fields.Float('To')
recurrency = fields.Selection([('once', 'Specific Day'), ('reccurent', 'Reccurent')], 'Recurrency', default='reccurent')
recurrency_from = fields.Float('From', default=7)
recurrency_to = fields.Float('To', default=23)
recurrency_date = fields.Date('Day', default=fields.Date.today())
recurrency_date_from = fields.Datetime('from', compute='_compute_recurrency_date_from', store=True)
recurrency_date_to = fields.Datetime('to', compute='_compute_recurrency_date_to', store=True)
recurrency_monday = fields.Boolean('Monday')
recurrency_tuesday = fields.Boolean('Tuesday')
recurrency_wednesday = fields.Boolean('Wednesday')
recurrency_thursday = fields.Boolean('Thursday')
recurrency_friday = fields.Boolean('Friday')
recurrency_monday = fields.Boolean('Monday', default=True)
recurrency_tuesday = fields.Boolean('Tuesday', default=True)
recurrency_wednesday = fields.Boolean('Wednesday', default=True)
recurrency_thursday = fields.Boolean('Thursday', default=True)
recurrency_friday = fields.Boolean('Friday', default=True)
recurrency_saturday = fields.Boolean('Saturday')
recurrency_sunday = fields.Boolean('Sunday')
@@ -142,7 +145,7 @@ def _compute_available_today(self):
time_to = float_to_time(supplier.recurrency_to)
if supplier.recurrency == 'once':
supplier.available_today = (supplier.reccurrency_date_from <= now <= supplier.reccurrency_date_to)
supplier.available_today = (supplier.recurrency_date_from <= now <= supplier.recurrency_date_to)
else:
fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[now.weekday()])
supplier.available_today = supplier[fieldname] and (time_from <= now.time() <= time_to)
@@ -11,3 +11,10 @@ product_user,"Product user",model_lunch_product,group_lunch_user,1,0,0,0
product_category_user,"Product category user",model_lunch_product_category,group_lunch_user,1,0,0,0
lunch_supplier_user,"Lunch Supplier User Rights",model_lunch_supplier,group_lunch_user,1,0,0,0
lunch_supplier_manager,"Lunch Supplier Manager Rights",model_lunch_supplier,group_lunch_manager,1,1,1,1
lunch_alert_access,access_lunch_alert_user,model_lunch_alert,base.group_user,1,0,0,0
lunch_alert_user,access_lunch_alert_lunch_user,model_lunch_alert,group_lunch_user,1,1,1,1
lunch_alert_manager,access_lunch_alert_manager,model_lunch_alert,group_lunch_manager,1,1,1,1
lunch_topping_type_user,access_lunch_topping_type,model_lunch_topping_type,base.group_user,1,0,0,0
lunch_topping_type_manager,access_lunch_topping_type,model_lunch_topping_type,group_lunch_manager,1,1,1,1
lunch_topping_user,access_lunch_topping,model_lunch_topping,base.group_user,1,0,0,0
lunch_topping_manager,access_lunch_topping,model_lunch_topping,group_lunch_manager,1,1,1,1
@@ -5,18 +5,17 @@
.o_lunch_widget {
display: flex;
overflow: auto;
border-bottom: 1px solid #CED4DA;
background-color: white;
min-height: 90px;
max-height: 90px;
overflow-y: visible;
.o_lunch_widget_info {
padding: 5px 12px;
margin: 4px 8px;
width: 300px;
flex: 1 1 auto;
overflow-y: auto;
overflow-y: visible;
.o_lunch_ordered {
color: white;
Oops, something went wrong.

2 comments on commit 6f5dc57

@fhe-odoo

This comment has been minimized.

Contributor

fhe-odoo replied Dec 7, 2018

Can you please make sure alerts are company aware?

@fpodoo

This comment has been minimized.

Contributor

fpodoo replied Dec 7, 2018

Please sign in to comment.