[REF] lunch: split lunch.py into smaller files

We should basically have one model per file, as this will facilitate the
reading and maintenance of the code
This commit is contained in:
RomainLibert
2018-12-04 11:55:07 +01:00
committed by Yannick Tivisse
parent a2c5b44df8
commit ad99f09a06
11 changed files with 855 additions and 840 deletions
+4
View File
@@ -28,6 +28,10 @@ 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/lucky_order_view.xml',
'views/lunch_alert_views.xml',
'views/lunch_cashmove_views.xml',
'views/lunch_orders_views.xml',
'views/lunch_product_views.xml',
'views/lunch_views.xml',
'data/lunch_data.xml',
],
+4 -1
View File
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
from . import lunch
from . import lunch_alert
from . import lunch_cashmove
from . import lunch_order
from . import lunch_product
+85
View File
@@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from odoo import api, fields, models, _
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'
display = fields.Boolean(compute='_compute_display_get')
message = fields.Text('Message', required=True)
alert_type = fields.Selection([('specific', 'Specific Day'),
('week', 'Every Week'),
('days', 'Every Day')],
string='Recurrence', required=True, index=True, default='specific')
partner_id = fields.Many2one('res.partner', string="Vendor",
help="If specified, the selected vendor can be ordered only on selected days")
specific_day = fields.Date('Day', default=fields.Date.context_today)
monday = fields.Boolean('Monday')
tuesday = fields.Boolean('Tuesday')
wednesday = fields.Boolean('Wednesday')
thursday = fields.Boolean('Thursday')
friday = fields.Boolean('Friday')
saturday = fields.Boolean('Saturday')
sunday = fields.Boolean('Sunday')
start_hour = fields.Float('Between', oldname='active_from', required=True, default=7)
end_hour = fields.Float('And', oldname='active_to', required=True, default=23)
active = fields.Boolean(default=True)
@api.multi
def name_get(self):
return [(alert.id, '%s %s' % (_('Alert'), '#%d' % alert.id)) for alert in self]
@api.depends('alert_type', 'specific_day', 'monday', 'tuesday', 'thursday',
'friday', 'saturday', 'sunday', 'start_hour', 'end_hour')
def _compute_display_get(self):
"""
This method check if the alert can be displayed today
if alert type is specific : compare specific_day(date) with today's date
if alert type is week : check today is set as alert (checkbox true) eg. self['monday']
if alert type is day : True
return : Message if can_display_alert is True else False
"""
days_codes = {'0': 'sunday',
'1': 'monday',
'2': 'tuesday',
'3': 'wednesday',
'4': 'thursday',
'5': 'friday',
'6': 'saturday'}
fullday = False
now = datetime.datetime.now()
if self.env.context.get('lunch_date'):
# lunch_date is a fields.Date -> 00:00:00
lunch_date = fields.Datetime.from_string(self.env.context['lunch_date'])
# if lunch_date is in the future, planned lunch, ignore hours
fullday = lunch_date > now
now = max(lunch_date, now)
mynow = fields.Datetime.context_timestamp(self, now)
for alert in self:
can_display_alert = {
'specific': (str(alert.specific_day) == fields.Date.to_string(mynow)),
'week': alert[days_codes[mynow.strftime('%w')]],
'days': True
}
if can_display_alert[alert.alert_type]:
hour_to = int(alert.end_hour)
min_to = int((alert.end_hour - hour_to) * 60)
to_alert = datetime.time(hour_to, min_to)
hour_from = int(alert.start_hour)
min_from = int((alert.start_hour - hour_from) * 60)
from_alert = datetime.time(hour_from, min_from)
if fullday or (from_alert <= mynow.time() <= to_alert):
alert.display = True
else:
alert.display = False
+23
View File
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class LunchCashMove(models.Model):
""" Two types of cashmoves: payment (credit) or order (debit) """
_name = 'lunch.cashmove'
_description = 'Lunch Cashmove'
user_id = fields.Many2one('res.users', 'User',
default=lambda self: self.env.uid)
date = fields.Date('Date', required=True, default=fields.Date.context_today)
amount = fields.Float('Amount', required=True, help='Can be positive (payment) or negative (order or payment if user wants to get his money back)')
description = fields.Text('Description', help='Can be an order or a payment')
order_id = fields.Many2one('lunch.order.line', 'Order', ondelete='cascade')
state = fields.Selection([('order', 'Order'), ('payment', 'Payment')],
'Is an order or a payment', default='payment')
@api.multi
def name_get(self):
return [(cashmove.id, '%s %s' % (_('Lunch Cashmove'), '#%d' % cashmove.id)) for cashmove in self]
@@ -4,12 +4,10 @@
from collections import OrderedDict
import json
import datetime
from odoo import api, fields, models, _
from odoo.exceptions import AccessError, ValidationError
from odoo.addons import decimal_precision as dp
from odoo.osv import expression
class LunchOrder(models.Model):
@@ -315,157 +313,3 @@ class LunchOrderLine(models.Model):
self.cashmove.unlink()
else:
raise AccessError(_("Only your lunch manager cancels the orders."))
class LunchProduct(models.Model):
""" Products available to order. A product is linked to a specific vendor. """
_name = 'lunch.product'
_description = 'Lunch Product'
name = fields.Char('Product', required=True)
category_id = fields.Many2one('lunch.product.category', 'Product Category', required=True)
description = fields.Text('Description')
price = fields.Float('Price', digits=dp.get_precision('Account'))
supplier = fields.Many2one('res.partner', 'Vendor')
active = fields.Boolean(default=True)
available = fields.Boolean(compute='_get_available_product', search='_search_available_products')
@api.depends('supplier')
def _get_available_product(self):
for product in self:
if not product.supplier:
product.available = True
else:
alerts = self.env['lunch.alert'].search([
('partner_id', '=', self.supplier.id)
])
if alerts and not any(alert.display for alert in alerts):
# every alert is not available
product.available = False
else:
# no alert for the supplier or at least one is not available
product.available = True
def _search_available_products(self, operator, value):
alerts = self.env['lunch.alert'].search([])
supplier_w_alerts = alerts.mapped('partner_id')
available_suppliers = alerts.filtered(lambda a: a.display).mapped('partner_id')
available_products = self.search([
'|',
('supplier', 'not in', supplier_w_alerts.ids),
('supplier', 'in', available_suppliers.ids)
])
if (operator in expression.NEGATIVE_TERM_OPERATORS and value) or \
(operator not in expression.NEGATIVE_TERM_OPERATORS and not value):
# e.g. (available = False) or (available != True)
return [('id', 'not in', available_products.ids)]
else:
# e.g. (available = True) or (available != False)
return [('id', 'in', available_products.ids)]
class LunchProductCategory(models.Model):
""" Category of the product such as pizza, sandwich, pasta, chinese, burger... """
_name = 'lunch.product.category'
_description = 'Lunch Product Category'
name = fields.Char('Product Category', required=True)
class LunchCashMove(models.Model):
""" Two types of cashmoves: payment (credit) or order (debit) """
_name = 'lunch.cashmove'
_description = 'Lunch Cashmove'
user_id = fields.Many2one('res.users', 'User',
default=lambda self: self.env.uid)
date = fields.Date('Date', required=True, default=fields.Date.context_today)
amount = fields.Float('Amount', required=True, help='Can be positive (payment) or negative (order or payment if user wants to get his money back)')
description = fields.Text('Description', help='Can be an order or a payment')
order_id = fields.Many2one('lunch.order.line', 'Order', ondelete='cascade')
state = fields.Selection([('order', 'Order'), ('payment', 'Payment')],
'Is an order or a payment', default='payment')
@api.multi
def name_get(self):
return [(cashmove.id, '%s %s' % (_('Lunch Cashmove'), '#%d' % cashmove.id)) for cashmove in self]
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'
display = fields.Boolean(compute='_compute_display_get')
message = fields.Text('Message', required=True)
alert_type = fields.Selection([('specific', 'Specific Day'),
('week', 'Every Week'),
('days', 'Every Day')],
string='Recurrence', required=True, index=True, default='specific')
partner_id = fields.Many2one('res.partner', string="Vendor",
help="If specified, the selected vendor can be ordered only on selected days")
specific_day = fields.Date('Day', default=fields.Date.context_today)
monday = fields.Boolean('Monday')
tuesday = fields.Boolean('Tuesday')
wednesday = fields.Boolean('Wednesday')
thursday = fields.Boolean('Thursday')
friday = fields.Boolean('Friday')
saturday = fields.Boolean('Saturday')
sunday = fields.Boolean('Sunday')
start_hour = fields.Float('Between', oldname='active_from', required=True, default=7)
end_hour = fields.Float('And', oldname='active_to', required=True, default=23)
active = fields.Boolean(default=True)
@api.multi
def name_get(self):
return [(alert.id, '%s %s' % (_('Alert'), '#%d' % alert.id)) for alert in self]
@api.depends('alert_type', 'specific_day', 'monday', 'tuesday', 'thursday',
'friday', 'saturday', 'sunday', 'start_hour', 'end_hour')
def _compute_display_get(self):
"""
This method check if the alert can be displayed today
if alert type is specific : compare specific_day(date) with today's date
if alert type is week : check today is set as alert (checkbox true) eg. self['monday']
if alert type is day : True
return : Message if can_display_alert is True else False
"""
days_codes = {'0': 'sunday',
'1': 'monday',
'2': 'tuesday',
'3': 'wednesday',
'4': 'thursday',
'5': 'friday',
'6': 'saturday'}
fullday = False
now = datetime.datetime.now()
if self.env.context.get('lunch_date'):
# lunch_date is a fields.Date -> 00:00:00
lunch_date = fields.Datetime.from_string(self.env.context['lunch_date'])
# if lunch_date is in the future, planned lunch, ignore hours
fullday = lunch_date > now
now = max(lunch_date, now)
mynow = fields.Datetime.context_timestamp(self, now)
for alert in self:
can_display_alert = {
'specific': (str(alert.specific_day) == fields.Date.to_string(mynow)),
'week': alert[days_codes[mynow.strftime('%w')]],
'days': True
}
if can_display_alert[alert.alert_type]:
hour_to = int(alert.end_hour)
min_to = int((alert.end_hour - hour_to) * 60)
to_alert = datetime.time(hour_to, min_to)
hour_from = int(alert.start_hour)
min_from = int((alert.start_hour - hour_from) * 60)
from_alert = datetime.time(hour_from, min_from)
if fullday or (from_alert <= mynow.time() <= to_alert):
alert.display = True
else:
alert.display = False
+63
View File
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.addons import decimal_precision as dp
from odoo.osv import expression
class LunchProductCategory(models.Model):
""" Category of the product such as pizza, sandwich, pasta, chinese, burger... """
_name = 'lunch.product.category'
_description = 'Lunch Product Category'
name = fields.Char('Product Category', required=True)
class LunchProduct(models.Model):
""" Products available to order. A product is linked to a specific vendor. """
_name = 'lunch.product'
_description = 'Lunch Product'
name = fields.Char('Product', required=True)
category_id = fields.Many2one('lunch.product.category', 'Product Category', required=True)
description = fields.Text('Description')
price = fields.Float('Price', digits=dp.get_precision('Account'))
supplier = fields.Many2one('res.partner', 'Vendor')
active = fields.Boolean(default=True)
available = fields.Boolean(compute='_get_available_product', search='_search_available_products')
@api.depends('supplier')
def _get_available_product(self):
for product in self:
if not product.supplier:
product.available = True
else:
alerts = self.env['lunch.alert'].search([
('partner_id', '=', self.supplier.id)
])
if alerts and not any(alert.display for alert in alerts):
# every alert is not available
product.available = False
else:
# no alert for the supplier or at least one is not available
product.available = True
def _search_available_products(self, operator, value):
alerts = self.env['lunch.alert'].search([])
supplier_w_alerts = alerts.mapped('partner_id')
available_suppliers = alerts.filtered(lambda a: a.display).mapped('partner_id')
available_products = self.search([
'|',
('supplier', 'not in', supplier_w_alerts.ids),
('supplier', 'in', available_suppliers.ids)
])
if (operator in expression.NEGATIVE_TERM_OPERATORS and value) or \
(operator not in expression.NEGATIVE_TERM_OPERATORS and not value):
# e.g. (available = False) or (available != True)
return [('id', 'not in', available_products.ids)]
else:
# e.g. (available = True) or (available != False)
return [('id', 'in', available_products.ids)]
+134
View File
@@ -0,0 +1,134 @@
<?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="Archived" domain="[('active','=',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="alert_type"/>
<field name='start_hour' widget='float_time'/>
<field name='end_hour' 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>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<group>
<group name="schedule" string="Schedule">
<group colspan="4">
<field name="alert_type"/>
<field name="specific_day"
attrs="{'invisible': [('alert_type','!=','specific')], 'required':[('alert_type','=','specific')]}"/>
<field name='start_hour' widget='float_time' />
<field name='end_hour' widget='float_time' />
</group>
<group name="weekdays" col="4" attrs="{'invisible': [('alert_type','!=','week')]}">
<field name="monday"/>
<field name="tuesday"/>
<field name="wednesday"/>
<field name="thursday"/>
<field name="friday"/>
<field name="saturday"/>
<field name="sunday"/>
</group>
</group>
<group name="vendor" string="Vendor">
<group name="partner" colspan="4">
<field name="partner_id"/>
<field name="display" invisible="True"/>
</group>
<div class="oe_grey" colspan="4"
attrs="{'invisible': ['|', ('partner_id', '=', False), ('display', '=', True)]}">
Products from this vendor can <strong>not</strong> be ordered at that moment.
</div>
<div class="oe_grey" colspan="4"
attrs="{'invisible': ['|', ('partner_id', '=', False), ('display', '=', False)]}">
Products from this vendor can be ordered at that moment.
</div>
</group>
</group>
<group string='Message'>
<field name='message' nolabel='1' placeholder="Write the message you want to display during the defined period..."/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_lunch_alert_kanban" model="ir.ui.view">
<field name="name">lunch.alert.kanban</field>
<field name="model">lunch.alert</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="message"/>
<field name="alert_type"/>
<field name='start_hour'/>
<field name='end_hour'/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<strong class="o_kanban_record_title"><t t-esc="record.message.value"/></strong>
</div>
<div class="row mb4">
<div class="col-6">
Between: <t t-esc="record.start_hour.value"/> -
<t t-esc="record.end_hour.value"/>
</div>
<div class="col-6">
<span class="badge badge-pill float-right">
<t t-esc="record.alert_type.value"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="lunch_alert_action" model="ir.actions.act_window">
<field name="name">Alerts</field>
<field name="res_model">lunch.alert</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_alert_view_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new lunch alert
</p><p>
Alerts are used to warn employee from possible issues concerning the lunch orders.
To create a lunch alert you have to define its recurrence, the time interval during which the alert should be executed and the message to display.
</p><p>
Example:<br/>
Recurency: Everyday,<br/>
Time interval: from 00h00 am to 11h59 pm,<br/>
Message: "You must order before 10h30 am".
</p>
</field>
</record>
</odoo>
+165
View File
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="lunch_cashmove_view_search" model="ir.ui.view">
<field name='name'>lunch.cashmove.search</field>
<field name='model'>lunch.cashmove</field>
<field name='arch' type='xml'>
<search string="lunch employee payment">
<field name="description"/>
<field name="user_id"/>
<filter name='is_payment' string="Payment" domain="[('state','=','payment')]"/>
<separator/>
<filter name='is_mine_group' string="My Account grouped" domain="[('user_id','=',uid)]" context="{'group_by':'user_id'}"/>
<filter name="group_by_user" string="By User" context="{'group_by':'user_id'}"/>
</search>
</field>
</record>
<record id="lunch_cashmove_view_search_2" model="ir.ui.view">
<field name='name'>lunch.cashmove.search</field>
<field name='model'>lunch.cashmove</field>
<field name='arch' type='xml'>
<search string="lunch cashmove">
<field name="description"/>
<field name="user_id"/>
<group expand="0" string="Group By">
<filter name='group_by_user' string="By Employee" context="{'group_by':'user_id'}"/>
</group>
</search>
</field>
</record>
<record id="lunch_cashmove_view_tree" model="ir.ui.view">
<field name="name">lunch.cashmove.tree</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<tree string="cashmove tree">
<field name="date"/>
<field name="user_id"/>
<field name="description"/>
<field name="amount" sum="Total"/>
</tree>
</field>
</record>
<record id="lunch_cashmove_view_tree_2" model="ir.ui.view">
<field name="name">lunch.cashmove.tree</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<tree string="cashmove tree" create='false'>
<field name="date"/>
<field name="description"/>
<field name="amount" sum="Total"/>
</tree>
</field>
</record>
<record id="lunch_cashmove_view_form" model="ir.ui.view">
<field name="name">lunch.cashmove.form</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<form string="cashmove form">
<sheet>
<group>
<field name="user_id" required="1"/>
<field name="date"/>
<field name="amount"/>
</group>
<label for='description'/>
<field name="description"/>
</sheet>
</form>
</field>
</record>
<record id="view_lunch_cashmove_kanban" model="ir.ui.view">
<field name="name">lunch.cashmove.kanban</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="date"/>
<field name="user_id"/>
<field name="description"/>
<field name="amount"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="row mb4">
<div class="col-8">
<span>
<strong class="o_kanban_record_title"><t t-esc="record.description.value"/></strong>
</span>
</div>
<div class="col-4 text-right">
<span class="badge badge-pill">
<strong><i class="fa fa-money" role="img" aria-label="Amount" title="Amount"/> <field name="amount"/></strong>
</span>
</div>
</div>
<div class="row">
<div class="col-6">
<i class="fa fa-clock-o" role="img" aria-label="Date" title="Date"/>
<t t-esc="record.date.value"/>
</div>
<div class="col-6">
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24" class="oe_kanban_avatar float-right"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="lunch_cashmove_action_account" model="ir.actions.act_window">
<field name="name">Your Account</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="lunch_cashmove_view_search"/>
<field name="context">{"search_default_is_mine_group":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree_2"/>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No cash move yet
</p><p>
Here you can see your cash moves.<br/>A cash move can either be an expense or a payment.
An expense is automatically created when an order is received while a payment is a reimbursement to the company encoded by the manager.
</p>
</field>
</record>
<record id="lunch_cashmove_action_control_accounts" model="ir.actions.act_window">
<field name="name">Control Accounts</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_cashmove_view_search_2"/>
<field name="context">{"search_default_group_by_user":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new payment
</p><p>
A cashmove can either be an expense or a payment.<br/>
An expense is automatically created at the order receipt.<br/>
A payment represents the employee reimbursement to the company.
</p>
</field>
</record>
<record id="lunch_cashmove_action_payment" model="ir.actions.act_window">
<field name="name">Register Cash Moves</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_cashmove_view_search"/>
<field name="context">{"search_default_is_payment":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Register a payment
</p><p>
Payments are used to register liquidity movements. You can process those payments by your own means or by using installed facilities.
</p>
</field>
</record>
</odoo>
+237
View File
@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="lunch_order_view_tree" model="ir.ui.view">
<field name="name">lunch.order.tree</field>
<field name="model">lunch.order</field>
<field name="arch" type="xml">
<tree string="Orders Tree">
<field name="date"/>
<field name="order_line_ids"/>
<field name="state"/>
<field name="total" sum="Total"/>
</tree>
</field>
</record>
<record id="lunch_order_view_form" model="ir.ui.view">
<field name="name">lunch.order.form</field>
<field name="model">lunch.order</field>
<field name="arch" type="xml">
<form string='Orders Form' class="o_lunch">
<header>
<button name="%(action_lunch_order_line_lucky)d" type="action" string="Feeling Lucky" class="oe_highlight"/>
<field name='state' widget='statusbar' statusbar_visible='new,confirmed'/>
</header>
<sheet>
<field name="balance_visible" invisible="1"/>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button"
attrs="{'invisible': [('balance_visible', '=', False)]}"
name="%(lunch_cashmove_action_account)d"
icon="fa-money"
type="action">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value"><field name="cash_move_balance" widget="monetary"/></span>
<span class="o_stat_text">Balance</span>
</div>
</button>
</div>
<group>
<group>
<field name='user_id' class="oe_inline" required='1'/>
<field name='date'/>
</group>
<div>
<div attrs="{'invisible': ['|',('state','!=','new'),('alerts','=',False)]}" class="alert alert-danger oe_edit_only" role="alert">
<field name='alerts'/>
</div>
</div>
</group>
<div>
<field name='previous_order_widget' widget='previous_order' class='o_lunch_last_orders'/>
</div>
<separator string='Select your order'/>
<field name='order_line_ids'>
<tree string='List' editable='bottom'>
<field name='product_id' context="{'lunch_date': parent.date}"/>
<field name='note' />
<field name='price'/>
<field name='supplier' invisible="1"/>
<field name="state" invisible="1"/>
</tree>
<form string='Lunch Order Form'>
<group>
<field name='product_id' context="{'lunch_date': parent.date}"/>
<field name='note' />
<field name='price'/>
</group>
</form>
</field>
<group class='oe_subtotal_footer oe_right'>
<field name='total' widget='monetary' options="{'currency_field': 'currency_id'}"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="lunch_order_line_view_search" model="ir.ui.view">
<field name="name">lunch.order.line.search</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<search string="Search">
<filter name='is_mine' string="My Orders" domain="[('user_id','=',uid)]"/>
<separator/>
<field name="name" string="Product" filter_domain="['|', ('name', 'ilike', self), ('note', 'ilike', self)]"/>
<filter name="not_confirmed" string="Not Received" domain="[('state','!=',('confirmed'))]"/>
<filter name="confirmed" string="Received" domain="[('state','=','confirmed')]"/>
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancelled')]"/>
<separator/>
<filter name="date_filter" string="Date" date="date" default_period="today"/>
<field name="user_id"/>
<group expand="0" string="Group By">
<filter name="group_by_order_id" string="By Order" context="{'group_by':'order_id'}"/>
<filter name="group_by_supplier" string="By Vendor" context="{'group_by':'supplier'}"/>
<filter name="group_by_date" string="Order Date" context="{'group_by':'date'}" help="Vendor Orders by Date"/>
</group>
</search>
</field>
</record>
<record id="lunch_order_line_view_tree" model="ir.ui.view">
<field name="name">lunch.order.line.tree</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<tree string="Order lines Tree" create="false" edit="false">
<field name='date'/>
<field name='supplier' invisible='1'/>
<field name='product_id'/>
<field name='note'/>
<field name='state'/>
<field name='user_id'/>
<field name='price' sum="Total" string="Price"/>
<button name="order" string="Order" type="object" icon="fa-phone text-success" attrs="{'invisible': ['|',('state','=','confirmed'),('state','=','ordered')]}" groups="lunch.group_lunch_manager"/>
<button name="confirm" string="Receive" type="object" icon="fa-check text-success" attrs="{'invisible': [('state','!=','ordered')]}" groups="lunch.group_lunch_manager"/>
<button name="cancel" string="Cancel" type="object" icon="fa-times-circle text-danger" attrs="{'invisible': [('state','=','cancelled')]}" groups="lunch.group_lunch_manager"/>
</tree>
</field>
</record>
<record id='lunch_order_line_view_kanban' model='ir.ui.view'>
<field name="name">lunch.order.line.kanban</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<kanban>
<field name='product_id'/>
<field name='note'/>
<field name='state'/>
<field name='user_id'/>
<field name='date'/>
<field name="price"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title"><field name="product_id"/></strong>
</div>
<field name="state" widget="kanban_label_selection" options="{'classes': {'new': 'default', 'confirmed': 'success', 'cancelled':'danger'}}"/>
</div>
<div>
<field name="note"/>
</div>
<div class="row">
<div class="col-6">
<i class="fa fa-money" role="img" aria-label="Money" title="Money"/> <field name="price"/>
</div>
<div class="col-6 text-right">
<i class="fa fa-clock-o" role="img" aria-label="Date" title="Date"/> <field name="date"/>
</div>
</div>
<div class="row mt4">
<div class="col-6">
<a class="btn btn-sm btn-success" role="button" name="order" string="Order" type="object" attrs="{'invisible': ['|',('state','=','confirmed'),('state','=','ordered')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-phone" role="img" aria-label="Order button" title="Order button"/>
</a>
<a class="btn btn-sm btn-info" role="button" name="confirm" string="Receive" type="object" attrs="{'invisible': [('state','!=','ordered')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-check" role="img" aria-label="Receive button" title="Receive button"/>
</a>
<a class="btn btn-sm btn-danger" role="button" name="cancel" string="Cancel" type="object" attrs="{'invisible': [('state','=','cancelled')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-times" role="img" aria-label="Cancel button" title="Cancel button"/>
</a>
</div>
<div class="col-6">
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24" class="oe_kanban_avatar float-right"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="lunch_order_action_form" model="ir.actions.act_window">
<field name="name">New Order</field>
<field name="res_model">lunch.order</field>
<field name="view_mode">form</field>
</record>
<record id="lunch_order_line_action" model="ir.actions.act_window">
<field name="name">Your Orders</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_is_mine":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No previous order found
</p><p>
There is no previous order recorded. Click on "My Lunch" and then create a new lunch order.
</p>
</field>
</record>
<record id="lunch_order_line_action_by_supplier" model="ir.actions.act_window">
<field name="name">Orders by Vendor</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_group_by_supplier":1, "search_default_date_filter":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
Nothing to order today
</p><p>
Here you can see today's orders grouped by vendors.
</p><p>
Click on the <span class="fa fa-phone text-success" role="img" aria-label="Order button" title="Order button"/> to announce that the order is ordered.<br/>
Click on the <span class="fa fa-check text-success" role="img" aria-label="Receive button" title="Receive button"/> to announce that the order is received.<br/>
Click on the <span class="fa fa-times-circle text-danger" role="img" aria-label="Cancel button" title="Cancel button"/> to announce that the order isn't available.
</p>
</field>
</record>
<record id="lunch_order_line_action_control_suppliers" model="ir.actions.act_window">
<field name="name">Control Vendors</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_group_by_date":1, "search_default_group_by_supplier":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No lunch order yet
</p><p>
Summary of all lunch orders, grouped by vendor and by date.
</p><p>
Click on the <span class="fa fa-phone text-success" role="img" aria-label="Order button" title="Order button"/> to announce that the order is ordered.<br/>
Click on the <span class="fa fa-check text-success" role="img" aria-label="Receive button" title="Receive button"/> to announce that the order is received.<br/>
Click on the <span class="fa fa-times-circle text-danger" role="img" aria-label="Cancel button" title="Cancel button"/> red X to announce that the order isn't available.
</p>
</field>
</record>
</odoo>
+140
View File
@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="lunch_product_view_search" model="ir.ui.view">
<field name="name">lunch.product.search</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<search string="Product Search">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<group expand="0" string="Group By">
<filter name="supplier" string="Vendor" context="{'group_by': 'supplier'}"/>
<filter name="category" string="Product Category" context="{'group_by': 'category_id'}"/>
<filter name="inactive" string="Archived" domain="[('active','=',False)]"/>
</group>
</search>
</field>
</record>
<record id="lunch_product_view_tree" model="ir.ui.view">
<field name="name">lunch.product.tree</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<tree string="Products Tree">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<field name="price"/>
</tree>
</field>
</record>
<record id="lunch_product_view_form" model="ir.ui.view">
<field name="name">lunch.product.form</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<form string="Products Form">
<header>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<group>
<group>
<field name='name'/>
<field name='category_id'/>
</group>
<group>
<field name='supplier'/>
<field name='price'/>
</group>
</group>
<label for='description'/>
<field name='description'/>
</sheet>
</form>
</field>
</record>
<record id="view_lunch_product_kanban" model="ir.ui.view">
<field name="name">lunch.product.kanban</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<field name="price"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title"><t t-esc="record.name.value"/></strong>
</div>
<span class="badge badge-pill float-right">
Price: <t t-esc="record.price.value"/>
</span>
</div>
<div>
<t t-esc="record.supplier.value"/>
</div>
<div>
<t t-esc="record.description.value"/>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="lunch_product_category_view_form" model="ir.ui.view">
<field name="name">Product category Form</field>
<field name="model">lunch.product.category</field>
<field name="arch" type="xml">
<form string="Products Form">
<sheet>
<group>
<field name='name' string="Product Category: "/>
</group>
</sheet>
</form>
</field>
</record>
<record id="lunch_product_action" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">lunch.product</field>
<field name="view_mode">tree,kanban,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new product for lunch
</p><p>
A product is defined by its name, category, price and vendor.
</p>
</field>
</record>
<record id="lunch_product_category_action" model="ir.actions.act_window">
<field name="name">Product Categories</field>
<field name="res_model">lunch.product.category</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new lunch category
</p><p>
Here you can access all categories for the lunch products.
</p>
</field>
</record>
</odoo>
-683
View File
@@ -6,549 +6,19 @@
<menuitem name="Manager" parent="menu_lunch" id="menu_lunch_admin" sequence="51" groups="group_lunch_manager"/>
<menuitem name="Configuration" parent="menu_lunch" id="menu_lunch_config" sequence="53" groups="group_lunch_manager"/>
<!--View Search to group/filter by Supplier and time-->
<record id="lunch_order_line_view_search" model="ir.ui.view">
<field name="name">lunch.order.line.search</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<search string="Search">
<filter name='is_mine' string="My Orders" domain="[('user_id','=',uid)]"/>
<separator/>
<field name="name" string="Product" filter_domain="['|', ('name', 'ilike', self), ('note', 'ilike', self)]"/>
<filter name="not_confirmed" string="Not Received" domain="[('state','!=',('confirmed'))]"/>
<filter name="confirmed" string="Received" domain="[('state','=','confirmed')]"/>
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancelled')]"/>
<separator/>
<filter name="date_filter" string="Date" date="date" default_period="today"/>
<field name="user_id"/>
<group expand="0" string="Group By">
<filter name="group_by_order_id" string="By Order" context="{'group_by':'order_id'}"/>
<filter name="group_by_supplier" string="By Vendor" context="{'group_by':'supplier'}"/>
<filter name="group_by_date" string="Order Date" context="{'group_by':'date'}" help="Vendor Orders by Date"/>
</group>
</search>
</field>
</record>
<!--View Search to group by employee and input/output (cashmoves)-->
<record id="lunch_cashmove_view_search" model="ir.ui.view">
<field name='name'>lunch.cashmove.search</field>
<field name='model'>lunch.cashmove</field>
<field name='arch' type='xml'>
<search string="lunch employee payment">
<field name="description"/>
<field name="user_id"/>
<filter name='is_payment' string="Payment" domain="[('state','=','payment')]"/>
<separator/>
<filter name='is_mine_group' string="My Account grouped" domain="[('user_id','=',uid)]" context="{'group_by':'user_id'}"/>
<filter name="group_by_user" string="By User" context="{'group_by':'user_id'}"/>
</search>
</field>
</record>
<record id="lunch_cashmove_view_search_2" model="ir.ui.view">
<field name='name'>lunch.cashmove.search</field>
<field name='model'>lunch.cashmove</field>
<field name='arch' type='xml'>
<search string="lunch cashmove">
<field name="description"/>
<field name="user_id"/>
<group expand="0" string="Group By">
<filter name='group_by_user' string="By Employee" context="{'group_by':'user_id'}"/>
</group>
</search>
</field>
</record>
<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="Archived" domain="[('active','=',False)]"/>
</search>
</field>
</record>
<!--view for cashmove-->
<record id="lunch_cashmove_view_tree" model="ir.ui.view">
<field name="name">lunch.cashmove.tree</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<tree string="cashmove tree">
<field name="date"/>
<field name="user_id"/>
<field name="description"/>
<field name="amount" sum="Total"/>
</tree>
</field>
</record>
<record id="view_lunch_cashmove_kanban" model="ir.ui.view">
<field name="name">lunch.cashmove.kanban</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="date"/>
<field name="user_id"/>
<field name="description"/>
<field name="amount"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="row mb4">
<div class="col-8">
<span>
<strong class="o_kanban_record_title"><t t-esc="record.description.value"/></strong>
</span>
</div>
<div class="col-4 text-right">
<span class="badge badge-pill">
<strong><i class="fa fa-money" role="img" aria-label="Amount" title="Amount"/> <field name="amount"/></strong>
</span>
</div>
</div>
<div class="row">
<div class="col-6">
<i class="fa fa-clock-o" role="img" aria-label="Date" title="Date"/>
<t t-esc="record.date.value"/>
</div>
<div class="col-6">
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24" class="oe_kanban_avatar float-right"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="lunch_cashmove_view_form" model="ir.ui.view">
<field name="name">lunch.cashmove.form</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<form string="cashmove form">
<sheet>
<group>
<field name="user_id" required="1"/>
<field name="date"/>
<field name="amount"/>
</group>
<label for='description'/>
<field name="description"/>
</sheet>
</form>
</field>
</record>
<!--Action for Your Orders-->
<record id="lunch_order_action_form" model="ir.actions.act_window">
<field name="name">New Order</field>
<field name="res_model">lunch.order</field>
<field name="view_mode">form</field>
</record>
<menuitem name="New Order" parent="menu_lunch_title" id="lunch_order_menu_form" action="lunch_order_action_form" sequence="1"/>
<record id="lunch_order_line_action" model="ir.actions.act_window">
<field name="name">Your Orders</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_is_mine":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No previous order found
</p><p>
There is no previous order recorded. Click on "My Lunch" and then create a new lunch order.
</p>
</field>
</record>
<menuitem name="Previous Orders" parent="menu_lunch_title" id="lunch_order_menu_tree" action="lunch_order_line_action" sequence="2"/>
<record id="lunch_cashmove_view_tree_2" model="ir.ui.view">
<field name="name">lunch.cashmove.tree</field>
<field name="model">lunch.cashmove</field>
<field name="arch" type="xml">
<tree string="cashmove tree" create='false'>
<field name="date"/>
<field name="description"/>
<field name="amount" sum="Total"/>
</tree>
</field>
</record>
<!--Action for Lunch cashmoves-->
<record id="lunch_cashmove_action_account" model="ir.actions.act_window">
<field name="name">Your Account</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="lunch_cashmove_view_search"/>
<field name="context">{"search_default_is_mine_group":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree_2"/>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No cash move yet
</p><p>
Here you can see your cash moves.<br/>A cash move can either be an expense or a payment.
An expense is automatically created when an order is received while a payment is a reimbursement to the company encoded by the manager.
</p>
</field>
</record>
<menuitem name="Your Lunch Account" parent="menu_lunch_title" id="lunch_cashmove_menu_form" action="lunch_cashmove_action_account" sequence="3"/>
<!--Action for Administrate Orders group by supplier-->
<record id="lunch_order_line_action_by_supplier" model="ir.actions.act_window">
<field name="name">Orders by Vendor</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_group_by_supplier":1, "search_default_date_filter":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
Nothing to order today
</p><p>
Here you can see today's orders grouped by vendors.
</p><p>
Click on the <span class="fa fa-phone text-success" role="img" aria-label="Order button" title="Order button"/> to announce that the order is ordered.<br/>
Click on the <span class="fa fa-check text-success" role="img" aria-label="Receive button" title="Receive button"/> to announce that the order is received.<br/>
Click on the <span class="fa fa-times-circle text-danger" role="img" aria-label="Cancel button" title="Cancel button"/> to announce that the order isn't available.
</p>
</field>
</record>
<menuitem name="Today's Orders" parent="menu_lunch_admin" id="lunch_order_line_menu_by_supplier" action="lunch_order_line_action_by_supplier" />
<!--Action for control Vendor -->
<record id="lunch_order_line_action_control_suppliers" model="ir.actions.act_window">
<field name="name">Control Vendors</field>
<field name="res_model">lunch.order.line</field>
<field name="view_mode">tree,kanban</field>
<field name="search_view_id" ref="lunch_order_line_view_search"/>
<field name="context">{"search_default_group_by_date":1, "search_default_group_by_supplier":1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No lunch order yet
</p><p>
Summary of all lunch orders, grouped by vendor and by date.
</p><p>
Click on the <span class="fa fa-phone text-success" role="img" aria-label="Order button" title="Order button"/> to announce that the order is ordered.<br/>
Click on the <span class="fa fa-check text-success" role="img" aria-label="Receive button" title="Receive button"/> to announce that the order is received.<br/>
Click on the <span class="fa fa-times-circle text-danger" role="img" aria-label="Cancel button" title="Cancel button"/> red X to announce that the order isn't available.
</p>
</field>
</record>
<menuitem name="Orders by Vendor" parent="menu_lunch_admin" id="lunch_order_line_menu_control_suppliers" action="lunch_order_line_action_control_suppliers" />
<!--Action for Control Accounts-->
<record id="lunch_cashmove_action_control_accounts" model="ir.actions.act_window">
<field name="name">Control Accounts</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_cashmove_view_search_2"/>
<field name="context">{"search_default_group_by_user":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new payment
</p><p>
A cashmove can either be an expense or a payment.<br/>
An expense is automatically created at the order receipt.<br/>
A payment represents the employee reimbursement to the company.
</p>
</field>
</record>
<menuitem name="Control Accounts" parent="menu_lunch_admin" id="lunch_cashmove_menu_control_accounts" action="lunch_cashmove_action_control_accounts"/>
<!--Action for Payment cashmove-->
<record id="lunch_cashmove_action_payment" model="ir.actions.act_window">
<field name="name">Register Cash Moves</field>
<field name="res_model">lunch.cashmove</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_cashmove_view_search"/>
<field name="context">{"search_default_is_payment":1}</field>
<field name="view_id" ref="lunch_cashmove_view_tree"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Register a payment
</p><p>
Payments are used to register liquidity movements. You can process those payments by your own means or by using installed facilities.
</p>
</field>
</record>
<menuitem name="Employee Payments" parent="menu_lunch_admin" id="lunch_cashmove_menu_payment" action="lunch_cashmove_action_payment"/>
<!--Action for Products-->
<record id="lunch_product_action" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">lunch.product</field>
<field name="view_mode">tree,kanban,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new product for lunch
</p><p>
A product is defined by its name, category, price and vendor.
</p>
</field>
</record>
<menuitem name="Products" parent="menu_lunch_config" id="lunch_product_menu" action="lunch_product_action"/>
<!--Action for Product categories-->
<record id="lunch_product_category_action" model="ir.actions.act_window">
<field name="name">Product Categories</field>
<field name="res_model">lunch.product.category</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new lunch category
</p><p>
Here you can access all categories for the lunch products.
</p>
</field>
</record>
<record id="lunch_product_category_view_form" model="ir.ui.view">
<field name="name">Product category Form</field>
<field name="model">lunch.product.category</field>
<field name="arch" type="xml">
<form string="Products Form">
<sheet>
<group>
<field name='name' string="Product Category: "/>
</group>
</sheet>
</form>
</field>
</record>
<menuitem name="Product Categories" parent="menu_lunch_config" id="lunch_product_category_menu" action="lunch_product_category_action" />
<!--Action for Alert-->
<record id="lunch_alert_action" model="ir.actions.act_window">
<field name="name">Alerts</field>
<field name="res_model">lunch.alert</field>
<field name="view_mode">tree,kanban,form</field>
<field name="search_view_id" ref="lunch_alert_view_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new lunch alert
</p><p>
Alerts are used to warn employee from possible issues concerning the lunch orders.
To create a lunch alert you have to define its recurrence, the time interval during which the alert should be executed and the message to display.
</p><p>
Example:<br/>
Recurency: Everyday,<br/>
Time interval: from 00h00 am to 11h59 pm,<br/>
Message: "You must order before 10h30 am".
</p>
</field>
</record>
<menuitem name="Alerts" parent="menu_lunch_config" id="lunch_alert_menu" action="lunch_alert_action" />
<!--View for Order lines-->
<record id="lunch_order_line_view_tree" model="ir.ui.view">
<field name="name">lunch.order.line.tree</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<tree string="Order lines Tree" create="false" edit="false">
<field name='date'/>
<field name='supplier' invisible='1'/>
<field name='product_id'/>
<field name='note'/>
<field name='state'/>
<field name='user_id'/>
<field name='price' sum="Total" string="Price"/>
<button name="order" string="Order" type="object" icon="fa-phone text-success" attrs="{'invisible': ['|',('state','=','confirmed'),('state','=','ordered')]}" groups="lunch.group_lunch_manager"/>
<button name="confirm" string="Receive" type="object" icon="fa-check text-success" attrs="{'invisible': [('state','!=','ordered')]}" groups="lunch.group_lunch_manager"/>
<button name="cancel" string="Cancel" type="object" icon="fa-times-circle text-danger" attrs="{'invisible': [('state','=','cancelled')]}" groups="lunch.group_lunch_manager"/>
</tree>
</field>
</record>
<record id='lunch_order_line_view_kanban' model='ir.ui.view'>
<field name="name">lunch.order.line.kanban</field>
<field name="model">lunch.order.line</field>
<field name="arch" type="xml">
<kanban>
<field name='product_id'/>
<field name='note'/>
<field name='state'/>
<field name='user_id'/>
<field name='date'/>
<field name="price"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title"><field name="product_id"/></strong>
</div>
<field name="state" widget="kanban_label_selection" options="{'classes': {'new': 'default', 'confirmed': 'success', 'cancelled':'danger'}}"/>
</div>
<div>
<field name="note"/>
</div>
<div class="row">
<div class="col-6">
<i class="fa fa-money" role="img" aria-label="Money" title="Money"/> <field name="price"/>
</div>
<div class="col-6 text-right">
<i class="fa fa-clock-o" role="img" aria-label="Date" title="Date"/> <field name="date"/>
</div>
</div>
<div class="row mt4">
<div class="col-6">
<a class="btn btn-sm btn-success" role="button" name="order" string="Order" type="object" attrs="{'invisible': ['|',('state','=','confirmed'),('state','=','ordered')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-phone" role="img" aria-label="Order button" title="Order button"/>
</a>
<a class="btn btn-sm btn-info" role="button" name="confirm" string="Receive" type="object" attrs="{'invisible': [('state','!=','ordered')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-check" role="img" aria-label="Receive button" title="Receive button"/>
</a>
<a class="btn btn-sm btn-danger" role="button" name="cancel" string="Cancel" type="object" attrs="{'invisible': [('state','=','cancelled')]}" groups="lunch.group_lunch_manager">
<i class="fa fa-times" role="img" aria-label="Cancel button" title="Cancel button"/>
</a>
</div>
<div class="col-6">
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value" width="24" height="24" class="oe_kanban_avatar float-right"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!--View for Your orders-->
<record id="lunch_order_view_tree" model="ir.ui.view">
<field name="name">lunch.order.tree</field>
<field name="model">lunch.order</field>
<field name="arch" type="xml">
<tree string="Orders Tree">
<field name="date"/>
<field name="order_line_ids"/>
<field name="state"/>
<field name="total" sum="Total"/>
</tree>
</field>
</record>
<record id="lunch_order_view_form" model="ir.ui.view">
<field name="name">lunch.order.form</field>
<field name="model">lunch.order</field>
<field name="arch" type="xml">
<form string='Orders Form' class="o_lunch">
<header>
<button name="%(action_lunch_order_line_lucky)d" type="action" string="Feeling Lucky" class="oe_highlight"/>
<field name='state' widget='statusbar' statusbar_visible='new,confirmed'/>
</header>
<sheet>
<field name="balance_visible" invisible="1"/>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button"
attrs="{'invisible': [('balance_visible', '=', False)]}"
name="%(lunch_cashmove_action_account)d"
icon="fa-money"
type="action">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value"><field name="cash_move_balance" widget="monetary"/></span>
<span class="o_stat_text">Balance</span>
</div>
</button>
</div>
<group>
<group>
<field name='user_id' class="oe_inline" required='1'/>
<field name='date'/>
</group>
<div>
<div attrs="{'invisible': ['|',('state','!=','new'),('alerts','=',False)]}" class="alert alert-danger oe_edit_only" role="alert">
<field name='alerts'/>
</div>
</div>
</group>
<div>
<field name='previous_order_widget' widget='previous_order' class='o_lunch_last_orders'/>
</div>
<separator string='Select your order'/>
<field name='order_line_ids'>
<tree string='List' editable='bottom'>
<field name='product_id' context="{'lunch_date': parent.date}"/>
<field name='note' />
<field name='price'/>
<field name='supplier' invisible="1"/>
<field name="state" invisible="1"/>
</tree>
<form string='Lunch Order Form'>
<group>
<field name='product_id' context="{'lunch_date': parent.date}"/>
<field name='note' />
<field name='price'/>
</group>
</form>
</field>
<group class='oe_subtotal_footer oe_right'>
<field name='total' widget='monetary' options="{'currency_field': 'currency_id'}"/>
</group>
</sheet>
</form>
</field>
</record>
<!--View for Products-->
<record id="lunch_product_view_tree" model="ir.ui.view">
<field name="name">lunch.product.tree</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<tree string="Products Tree">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<field name="price"/>
</tree>
</field>
</record>
<record id="view_lunch_product_kanban" model="ir.ui.view">
<field name="name">lunch.product.kanban</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<field name="price"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title"><t t-esc="record.name.value"/></strong>
</div>
<span class="badge badge-pill float-right">
Price: <t t-esc="record.price.value"/>
</span>
</div>
<div>
<t t-esc="record.supplier.value"/>
</div>
<div>
<t t-esc="record.description.value"/>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="action_server_lunch_archive_product" model="ir.actions.server">
<field name="name">Lunch: Archive/Restore products</field>
@@ -558,157 +28,4 @@
<field name="state">code</field>
<field name="code">records.toggle_active()</field>
</record>
<!-- Search for product -->
<record id="lunch_product_view_search" model="ir.ui.view">
<field name="name">lunch.product.search</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<search string="Product Search">
<field name="name"/>
<field name="category_id"/>
<field name="supplier"/>
<field name="description"/>
<group expand="0" string="Group By">
<filter name="supplier" string="Vendor" context="{'group_by': 'supplier'}"/>
<filter name="category" string="Product Category" context="{'group_by': 'category_id'}"/>
<filter name="inactive" string="Archived" domain="[('active','=',False)]"/>
</group>
</search>
</field>
</record>
<record id="lunch_product_view_form" model="ir.ui.view">
<field name="name">lunch.product.form</field>
<field name="model">lunch.product</field>
<field name="arch" type="xml">
<form string="Products Form">
<header>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<group>
<group>
<field name='name'/>
<field name='category_id'/>
</group>
<group>
<field name='supplier'/>
<field name='price'/>
</group>
</group>
<label for='description'/>
<field name='description'/>
</sheet>
</form>
</field>
</record>
<!--view for alerts-->
<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="alert_type"/>
<field name='start_hour' widget='float_time'/>
<field name='end_hour' widget='float_time'/>
</tree>
</field>
</record>
<record id="view_lunch_alert_kanban" model="ir.ui.view">
<field name="name">lunch.alert.kanban</field>
<field name="model">lunch.alert</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="message"/>
<field name="alert_type"/>
<field name='start_hour'/>
<field name='end_hour'/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="o_kanban_record_top">
<strong class="o_kanban_record_title"><t t-esc="record.message.value"/></strong>
</div>
<div class="row mb4">
<div class="col-6">
Between: <t t-esc="record.start_hour.value"/> -
<t t-esc="record.end_hour.value"/>
</div>
<div class="col-6">
<span class="badge badge-pill float-right">
<t t-esc="record.alert_type.value"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</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>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<group>
<group name="schedule" string="Schedule">
<group colspan="4">
<field name="alert_type"/>
<field name="specific_day"
attrs="{'invisible': [('alert_type','!=','specific')], 'required':[('alert_type','=','specific')]}"/>
<field name='start_hour' widget='float_time' />
<field name='end_hour' widget='float_time' />
</group>
<group name="weekdays" col="4" attrs="{'invisible': [('alert_type','!=','week')]}">
<field name="monday"/>
<field name="tuesday"/>
<field name="wednesday"/>
<field name="thursday"/>
<field name="friday"/>
<field name="saturday"/>
<field name="sunday"/>
</group>
</group>
<group name="vendor" string="Vendor">
<group name="partner" colspan="4">
<field name="partner_id"/>
<field name="display" invisible="True"/>
</group>
<div class="oe_grey" colspan="4"
attrs="{'invisible': ['|', ('partner_id', '=', False), ('display', '=', True)]}">
Products from this vendor can <strong>not</strong> be ordered at that moment.
</div>
<div class="oe_grey" colspan="4"
attrs="{'invisible': ['|', ('partner_id', '=', False), ('display', '=', False)]}">
Products from this vendor can be ordered at that moment.
</div>
</group>
</group>
<group string='Message'>
<field name='message' nolabel='1' placeholder="Write the message you want to display during the defined period..."/>
</group>
</sheet>
</form>
</field>
</record>
</odoo>