Revert "[IMP] lunch: reintroduce lunch_alerts, change display of wizard"
This reverts commit 6f5dc5733f.
This commit is contained in:
@@ -28,7 +28,6 @@ If you want to save your employees' time and avoid them to always have coins in
|
||||
'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,7 +17,6 @@ class LunchController(http.Controller):
|
||||
'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,15 +285,11 @@
|
||||
<field name="image" type="base64" file="lunch/static/img/napoli.png"/>
|
||||
</record>
|
||||
|
||||
<record model="lunch.topping.type" id="type_garniture">
|
||||
<field name="name">Garniture</field>
|
||||
</record>
|
||||
|
||||
<record model="lunch.topping" id="product_olives">
|
||||
<record model="lunch.product" id="product_olives">
|
||||
<field name="name">Olives</field>
|
||||
<field name="price">0.30</field>
|
||||
<field name="category_id" ref="categ_pizza"/>
|
||||
<field name="type_id" ref="type_garniture"/>
|
||||
<field name="supplier_id" eval="str(ref('supplier_pizza_inn'))"/>
|
||||
<field name="is_topping" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="lunch.product" id="product_4formaggi">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import lunch_alert
|
||||
from . import lunch_cashmove
|
||||
from . import lunch_order
|
||||
from . import lunch_product
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
# -*- 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.topping', string='Toppings')
|
||||
product_id = fields.Many2one('lunch.product', string="Product", required=True)
|
||||
topping_ids = fields.Many2many('lunch.product', string='Toppings')
|
||||
product_id = fields.Many2one('lunch.product', string="Product", domain=[('is_topping', '=', False)], 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 * (line.product_id.price + sum(line.topping_ids.mapped('price')))
|
||||
line.price = line.quantity * sum(product.price for product in line.product_id | line.topping_ids)
|
||||
|
||||
def update_quantity(self, increment):
|
||||
for line in self:
|
||||
|
||||
@@ -14,37 +14,6 @@ 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):
|
||||
@@ -53,11 +22,12 @@ class LunchProduct(models.Model):
|
||||
_description = 'Lunch Product'
|
||||
|
||||
name = fields.Char('Name', required=True)
|
||||
category_id = fields.Many2one('lunch.product.category', 'Product Category', required=True)
|
||||
category_id = fields.Many2one('lunch.product.category', 'Product Category')
|
||||
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,9 +49,6 @@ 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)
|
||||
@@ -63,17 +60,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='reccurent')
|
||||
recurrency_from = fields.Float('From', default=7)
|
||||
recurrency_to = fields.Float('To', default=23)
|
||||
recurrency = fields.Selection([('once', 'Specific Day'), ('reccurent', 'Reccurent')], 'Recurrency', default='once')
|
||||
recurrency_from = fields.Float('From')
|
||||
recurrency_to = fields.Float('To')
|
||||
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', 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_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')
|
||||
|
||||
@@ -145,7 +142,7 @@ class LunchSupplier(models.Model):
|
||||
time_to = float_to_time(supplier.recurrency_to)
|
||||
|
||||
if supplier.recurrency == 'once':
|
||||
supplier.available_today = (supplier.recurrency_date_from <= now <= supplier.recurrency_date_to)
|
||||
supplier.available_today = (supplier.reccurrency_date_from <= now <= supplier.reccurrency_date_to)
|
||||
else:
|
||||
fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[now.weekday()])
|
||||
supplier.available_today = supplier[fieldname] and (time_from <= now.time() <= time_to)
|
||||
|
||||
@@ -11,10 +11,3 @@ 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,17 +5,18 @@
|
||||
|
||||
.o_lunch_widget {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #CED4DA;
|
||||
background-color: white;
|
||||
min-height: 90px;
|
||||
overflow-y: visible;
|
||||
max-height: 90px;
|
||||
|
||||
.o_lunch_widget_info {
|
||||
padding: 5px 12px;
|
||||
margin: 4px 8px;
|
||||
width: 300px;
|
||||
flex: 1 1 auto;
|
||||
overflow-y: visible;
|
||||
overflow-y: auto;
|
||||
|
||||
.o_lunch_ordered {
|
||||
color: white;
|
||||
|
||||
@@ -1,108 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates>
|
||||
<div t-name="LunchKanbanWidget">
|
||||
<div class="o_lunch_widget">
|
||||
<div class="o_lunch_widget_info d-flex flex-row">
|
||||
<div class="o_lunch_widget" t-name="LunchKanbanWidget">
|
||||
<div class="o_lunch_widget_info d-flex flex-row">
|
||||
<div>
|
||||
<img class="rounded-circle" t-attf-src="{{ widget.data.userimage }}"/>
|
||||
</div>
|
||||
<div class="w-50 ml-2 py-3">
|
||||
<div>
|
||||
<img class="rounded-circle" t-attf-src="{{ widget.data.userimage }}"/>
|
||||
</div>
|
||||
<div class="w-50 ml-2 py-3">
|
||||
<div>
|
||||
<t t-if="widget.data.is_manager">
|
||||
<select class="o_input">
|
||||
<t t-foreach="widget.data.users" t-as="user">
|
||||
<option t-attf-data-user-id="{{ user.id }}" t-attf-value="{{ user.name }}"><t t-esc="user.name"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-esc="widget.data.username"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="d-flex flex-row">
|
||||
<span class="flex-grow-1">
|
||||
<i class="fa fa-money"/>
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="widget.data.wallet"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
<t t-if="widget.data.is_manager">
|
||||
<select class="o_input">
|
||||
<t t-foreach="widget.data.users" t-as="user">
|
||||
<option t-attf-data-user-id="{{ user.id }}" t-attf-value="{{ user.name }}"><t t-esc="user.name"/></option>
|
||||
</t>
|
||||
</span>
|
||||
<span>
|
||||
<a class="o_add_money" href="#">Add money</a>
|
||||
</span>
|
||||
</div>
|
||||
</select>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-esc="widget.data.username"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="d-flex flex-row">
|
||||
<span class="flex-grow-1">
|
||||
<i class="fa fa-money"/>
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="widget.data.wallet"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</span>
|
||||
<span>
|
||||
<a class="o_add_money" href="#">Add money</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_lunch_widget_info">
|
||||
<t t-if="widget.data.order">
|
||||
<t t-if="widget.data.state == 'ordered'">
|
||||
<t t-set="state_class" t-value="'o_lunch_ordered'"/>
|
||||
</t>
|
||||
<t t-else="widget.data.state == 'confirmed'">
|
||||
<t t-set="state_class" t-value="'o_lunch_confirmed'"/>
|
||||
</t>
|
||||
<div class="d-flex flex-row">
|
||||
<div class="flex-grow-1">
|
||||
<span class="o_lunch_widget_title">Your order</span>
|
||||
<a href="#"><i t-if="widget.data.state != 'confirmed'" class="fa fa-trash o_lunch_widget_unlink"/></a>
|
||||
<a t-if="widget.data.state == 'ordered' && !widget.data.edit" href="#" class="o_lunch_widget_edit">Edit</a>
|
||||
<a t-if="widget.data.state == 'ordered' && widget.data.edit" href="#" class="o_lunch_widget_save">Save</a>
|
||||
</div>
|
||||
<div t-if="widget.data.state != 'new'" t-esc="widget.data.state" t-attf-class="flex-grow-0 {{ state_class }}"/>
|
||||
</div>
|
||||
<div t-foreach="widget.data.lines" t-as="line">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="flex-grow-0">
|
||||
<a class="o_remove_product" t-if="widget.data.state == 'new' || widget.data.edit" t-attf-data-id="{{ line.id }}" href="#"><i class="fa fa-minus-circle"/></a>
|
||||
<span t-esc="line.quantity"/>
|
||||
<a class="o_add_product" t-if="widget.data.state == 'new' || widget.data.edit" t-attf-data-id="{{ line.id }}" href="#"><i class="fa fa-plus-circle"/></a>
|
||||
</div>
|
||||
<div class="flex-grow-1 pl-2">
|
||||
<span t-esc="line.product[0]"/>
|
||||
</div>
|
||||
<div class="flex-grow-0">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="line.product[1]"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-foreach="line.toppings" t-as="topping" class="d-flex flex-row">
|
||||
<div class="flex-grow-1 pl-5 ml-5">
|
||||
<span>+ <t t-esc="topping[0]"/></span>
|
||||
</div>
|
||||
<div class="flex-grow-0">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="topping[1]"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="o_lunch_widget_info">
|
||||
<t t-if="widget.data.order && widget.data.state == 'new'">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="o_lunch_widget_title flex-grow-1">
|
||||
Total
|
||||
</div>
|
||||
<div class="flex-grow-0 pr-1">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="widget.data.total"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary o_lunch_widget_order_button" t-attf-data-order-id="{{ widget.data.order }}">ORDER NOW</button>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="widget.data.alerts" t-as="alert">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<t t-esc="alert.message"/>
|
||||
</div>
|
||||
</t>
|
||||
<div class="o_lunch_widget_info">
|
||||
<t t-if="widget.data.order">
|
||||
<t t-if="widget.data.state == 'ordered'">
|
||||
<t t-set="state_class" t-value="'o_lunch_ordered'"/>
|
||||
</t>
|
||||
<t t-else="widget.data.state == 'confirmed'">
|
||||
<t t-set="state_class" t-value="'o_lunch_confirmed'"/>
|
||||
</t>
|
||||
<div class="d-flex flex-row">
|
||||
<div class="flex-grow-1">
|
||||
<span class="o_lunch_widget_title">Your order</span>
|
||||
<a href="#"><i t-if="widget.data.state != 'confirmed'" class="fa fa-trash o_lunch_widget_unlink"/></a>
|
||||
<a t-if="widget.data.state == 'ordered' && !widget.data.edit" href="#" class="o_lunch_widget_edit">Edit</a>
|
||||
<a t-if="widget.data.state == 'ordered' && widget.data.edit" href="#" class="o_lunch_widget_save">Save</a>
|
||||
</div>
|
||||
<div t-if="widget.data.state != 'new'" t-esc="widget.data.state" t-attf-class="flex-grow-0 {{ state_class }}"/>
|
||||
</div>
|
||||
<div t-foreach="widget.data.lines" t-as="line">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="flex-grow-0">
|
||||
<a class="o_remove_product" t-if="widget.data.state == 'new' || widget.data.edit" t-attf-data-id="{{ line.id }}" href="#"><i class="fa fa-minus-circle"/></a>
|
||||
<span t-esc="line.quantity"/>
|
||||
<a class="o_add_product" t-if="widget.data.state == 'new' || widget.data.edit" t-attf-data-id="{{ line.id }}" href="#"><i class="fa fa-plus-circle"/></a>
|
||||
</div>
|
||||
<div class="flex-grow-1 pl-2">
|
||||
<span t-esc="line.product[0]"/>
|
||||
</div>
|
||||
<div class="flex-grow-0">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="line.product[1]"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-foreach="line.toppings" t-as="topping" class="d-flex flex-row">
|
||||
<div class="flex-grow-1 pl-5 ml-5">
|
||||
<span>+ <t t-esc="topping[0]"/></span>
|
||||
</div>
|
||||
<div class="flex-grow-0">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="topping[1]"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="o_lunch_widget_info">
|
||||
<t t-if="widget.data.order && widget.data.state == 'new'">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="o_lunch_widget_title flex-grow-1">
|
||||
Total
|
||||
</div>
|
||||
<div class="flex-grow-0 pr-1">
|
||||
<t t-call="currency_field">
|
||||
<t t-set="value" t-value="widget.data.total"/>
|
||||
<t t-set="currency" t-value="widget.currency"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary o_lunch_widget_order_button" t-attf-data-order-id="{{ widget.data.order }}">ORDER NOW</button>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<t t-name="currency_field">
|
||||
|
||||
@@ -49,8 +49,7 @@ QUnit.module('Views', {
|
||||
state: 'new',
|
||||
lines: [
|
||||
{id: 1, product: ['Pizza Italiana', 7.4], toppings: [], quantity: 1.0, price: 7.4}
|
||||
],
|
||||
alerts: [],
|
||||
]
|
||||
});
|
||||
} else if (route.startsWith('data:image/png;base64,')) {
|
||||
return $.when();
|
||||
@@ -112,8 +111,7 @@ QUnit.module('Views', {
|
||||
state: state,
|
||||
lines: [
|
||||
{id: 1, product: ['Pizza Italiana', 7.4], toppings: [], quantity: 1.0, price: 7.4}
|
||||
],
|
||||
alerts: [],
|
||||
]
|
||||
});
|
||||
} else if (route === '/lunch/payment_message') {
|
||||
return $.when({message: 'Hello'});
|
||||
@@ -184,8 +182,7 @@ QUnit.module('Views', {
|
||||
state: 'new',
|
||||
lines: [
|
||||
{id: 1, product: ['Pizza Italiana', 7.4], toppings: [], quantity: 1.0, price: 7.4}
|
||||
],
|
||||
alerts: [],
|
||||
]
|
||||
});
|
||||
} else if (route.startsWith('data:image/png;base64,')) {
|
||||
return $.when();
|
||||
|
||||
@@ -67,13 +67,9 @@ class TestsCommon(common.TransactionCase):
|
||||
'supplier_id': self.supplier_coin_gourmand.id,
|
||||
})
|
||||
|
||||
self.garniture_type = self.env['lunch.topping.type'].create({
|
||||
'name': 'Graniture',
|
||||
})
|
||||
|
||||
self.topping_olives = self.env['lunch.topping'].create({
|
||||
self.topping_olives = self.env['lunch.product'].create({
|
||||
'name': 'Olives',
|
||||
'price': 0.3,
|
||||
'category_id': self.category_pizza.id,
|
||||
'type_id': self.garniture_type.id,
|
||||
'supplier_id': self.supplier_pizza_inn.id,
|
||||
'is_topping': True,
|
||||
})
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="lunch_alert_view_search" model="ir.ui.view">
|
||||
<field name="name">lunch.alert.search</field>
|
||||
<field name="model">lunch.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search">
|
||||
<field name="message"/>
|
||||
<filter name="inactive" string="Currently inactive" domain="[('available_today','=',False)]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_alert_view_tree" model="ir.ui.view">
|
||||
<field name="name">lunch.alert.tree</field>
|
||||
<field name="model">lunch.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="message"/>
|
||||
<field name="recurrency"/>
|
||||
<field name='recurrency_from' widget='float_time'/>
|
||||
<field name='recurrency_to' widget='float_time'/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_alert_view_form" model="ir.ui.view">
|
||||
<field name="name">lunch.alert.form</field>
|
||||
<field name="model">lunch.alert</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="alert form">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="recurrency"/>
|
||||
<field name="recurrency_date" attrs="{'invisible': [('recurrency', '!=', 'once')]}"/>
|
||||
<field name="recurrency_monday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_tuesday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_wednesday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_thursday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_friday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_saturday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_sunday" attrs="{'invisible': [('recurrency', '!=', 'reccurent')]}"/>
|
||||
<field name="recurrency_from" widget="float_time"/>
|
||||
<field name="recurrency_to" widget="float_time"/>
|
||||
</group>
|
||||
<label for='message'/>
|
||||
<field name="message"/>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_alert_action" model="ir.actions.act_window">
|
||||
<field name="name">Lunch Alerts</field>
|
||||
<field name="res_model">lunch.alert</field>
|
||||
<field name="search_view_id" ref="lunch_alert_view_search"/>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="lunch_alert_view_tree"/>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -11,8 +11,8 @@
|
||||
<field name="description"/>
|
||||
<filter name="inactive" string="Archived" domain="[('active','=',False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_by_supplier" string="Vendor" context="{'group_by': 'supplier_id'}"/>
|
||||
<filter name="group_by_category" string="Product Category" context="{'group_by': 'category_id'}"/>
|
||||
<filter name="supplier" string="Vendor" context="{'group_by': 'supplier_id'}"/>
|
||||
<filter name="category" string="Product Category" context="{'group_by': 'category_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -48,8 +48,12 @@
|
||||
<field name="image" widget="image" class="oe_avatar" options="{'preview_image': 'image_medium'}"/>
|
||||
<label for="name"/>
|
||||
<field name='name'/>
|
||||
<div>
|
||||
<field name="is_topping"/>
|
||||
<label for="is_topping"/>
|
||||
</div>
|
||||
<group>
|
||||
<field name='category_id'/>
|
||||
<field name='category_id' attrs="{'invisible': [('is_topping', '=', True)], 'required': [('is_topping', '=', False)]}"/>
|
||||
<field name='supplier_id'/>
|
||||
<field name='price'/>
|
||||
</group>
|
||||
@@ -68,7 +72,7 @@
|
||||
<field name="name">lunch.product.kanban</field>
|
||||
<field name="model">lunch.product</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban js_class="lunch_kanban" create="0" edit="0" group_create="0" group_edit="0" group_delete="0" class="o_kanban_mobile">
|
||||
<kanban js_class="lunch_kanban" create="0" class="o_kanban_mobile">
|
||||
<field name="id"/>
|
||||
<field name="name"/>
|
||||
<field name="category_id"/>
|
||||
@@ -111,7 +115,7 @@
|
||||
<field name="name">Product category Tree</field>
|
||||
<field name="model">lunch.product.category</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Products List">
|
||||
<tree string="Products List" editable="bottom">
|
||||
<field name='name' string="Product Category: "/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -124,14 +128,7 @@
|
||||
<form string="Products Form">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name" string="Product Category: "/>
|
||||
<field name="topping_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="type_id"/>
|
||||
<field name="name"/>
|
||||
<field name="price"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name='name' string="Product Category: "/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
@@ -155,8 +152,7 @@
|
||||
<field name="name">Order</field>
|
||||
<field name="res_model">lunch.product</field>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="search_view_id" ref="lunch_product_view_search"/>
|
||||
<field name="domain">[('supplier_id.available_today', '=', True)]</field>
|
||||
<field name="domain">[('is_topping', '=', False), ('supplier_id.available_today', '=', True)]</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_product_category_action" model="ir.actions.act_window">
|
||||
|
||||
@@ -40,9 +40,6 @@
|
||||
<field name="email"/>
|
||||
<field name="phone"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="responsible_id"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Availability">
|
||||
<group>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
<menuitem name="Vendors" parent="menu_lunch_config" id="lunch_vendors_menu" action="lunch_vendors_action" sequence="1"/>
|
||||
<menuitem name="Products" parent="menu_lunch_config" id="lunch_product_menu" action="lunch_product_action" sequence="2"/>
|
||||
<menuitem name="Product Categories" parent="menu_lunch_config" id="lunch_product_category_menu" action="lunch_product_category_action" sequence="3"/>
|
||||
<menuitem name="Alerts" parent="menu_lunch_config" id="lunch_alert_menu" action="lunch_alert_action" sequence="4"/>
|
||||
|
||||
|
||||
<record id="action_server_lunch_archive_product" model="ir.actions.server">
|
||||
|
||||
@@ -10,20 +10,11 @@ class LunchOrderLineWizard(models.TransientModel):
|
||||
_name = 'lunch.order.line.temp'
|
||||
_description = 'Lunch Order Line Temp'
|
||||
|
||||
def _default_topping_ids(self):
|
||||
last_time_ordered = self.env['lunch.order.line'].search([('product_id', '=', self.env.context.get('default_product_id', 0))],
|
||||
order="date desc", limit=1)
|
||||
return last_time_ordered.topping_ids
|
||||
|
||||
currency_id = fields.Many2one('res.currency', default=lambda self: self.env.user.company_id.currency_id)
|
||||
|
||||
product_id = fields.Many2one('lunch.product', string='Product ID')
|
||||
product_description = fields.Text('Description', related='product_id.description')
|
||||
product_name = fields.Char('Product', related='product_id.name')
|
||||
product_category = fields.Many2one('lunch.product.category', related='product_id.category_id')
|
||||
topping_ids = fields.Many2many('lunch.topping', string="Extra Garniture", domain="[('category_id', '=', product_category)]", default=_default_topping_ids)
|
||||
|
||||
available_toppings = fields.Boolean(help='Are toppings available for this product', compute='_compute_available_toppings')
|
||||
product_supplier = fields.Many2one('lunch.supplier', related='product_id.supplier_id')
|
||||
topping_ids = fields.Many2many('lunch.product', string="Extra Garniture", domain="[('is_topping', '=', True), ('supplier_id', '=', product_supplier)]")
|
||||
|
||||
quantity = fields.Float('Quantity', default=1)
|
||||
price_total = fields.Float('Total Price', compute='_compute_price_total')
|
||||
@@ -31,15 +22,10 @@ class LunchOrderLineWizard(models.TransientModel):
|
||||
|
||||
user_id = fields.Many2one('res.users', default=lambda self: self.env.user.id)
|
||||
|
||||
@api.depends('product_id')
|
||||
def _compute_available_toppings(self):
|
||||
for wizard in self:
|
||||
wizard.available_toppings = bool(wizard.env['lunch.topping'].search_count([('category_id', '=', wizard.product_category.id)]))
|
||||
|
||||
@api.depends('product_id', 'topping_ids', 'quantity')
|
||||
def _compute_price_total(self):
|
||||
for wizard in self:
|
||||
wizard.price_total = wizard.quantity * (wizard.product_id.price + sum(wizard.topping_ids.mapped('price')))
|
||||
wizard.price_total = wizard.quantity * sum(record.price for record in (wizard.product_id | wizard.topping_ids))
|
||||
|
||||
def find_current_order(self):
|
||||
order_id = self.env['lunch.order'].search([('state', '!=', 'cancel'),
|
||||
|
||||
@@ -7,24 +7,25 @@
|
||||
<field name="model">lunch.order.line.temp</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="quantity" invisible="1"/>
|
||||
<field name="product_id" invisible="1"/>
|
||||
<field name="product_category" invisible="1"/>
|
||||
<h2 class="d-flex">
|
||||
<div class="flex-grow-1 pr-5"><field name="product_name"/></div>
|
||||
<div class="flex-grow-0"><field name="price_total" widget="monetary"/></div>
|
||||
</h2>
|
||||
<group>
|
||||
<field name="available_toppings" invisible="1"/>
|
||||
<field name="topping_ids" attrs="{'invisible': [('available_toppings', '=', False)]}" widget="many2many_checkboxes"/>
|
||||
<field name="product_id" invisible="1"/>
|
||||
<field name="product_supplier" invisible="1"/>
|
||||
<field name="product_name"/>
|
||||
<field name="product_description"/>
|
||||
<field name="topping_ids" widget="many2many_tags"/>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<field name="note"/>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<field name="quantity"/>
|
||||
<field name="price_total" widget="monetary"/>
|
||||
</group>
|
||||
|
||||
<footer>
|
||||
<button name="add_to_cart" string="Add To Cart" type="object" class="oe_highlight"/>
|
||||
<button string="Discard" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
Reference in New Issue
Block a user