[IMP] lunch: new lunch widget
The JS widget is simplified, which a cleaner approach. For the rendering part: - the server reads the data - the JS widget formats/organizes the data - the template renders the data prepared by the widget Quick summary of the modifications: 1. The associated field is a text field which contains JSON-encoded data. The data are read server-side, and not client-side anymore. 2. The widget is an AbstractField, no need of ReinitializeWidgetMixin anymore. No use of the FieldMonetary widget directly, but use a similar format_value instead (inspired by ShowPaymentLineWidget). 3. Data formatting (call to format_value) is done in the widget, not in the template anymore. This seems to be the standard way of doing, since lunch was the only module where format_value was in the template and not in the widget. 4. The addition of an order line is cleaner since all necessary data are prepared server-side.
This commit is contained in:
committed by
Yannick Tivisse
parent
7cf554af54
commit
018144b8ac
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
import datetime
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
@@ -42,12 +43,12 @@ class LunchOrder(models.Model):
|
||||
'Status', readonly=True, index=True, copy=False,
|
||||
compute='_compute_order_state', store=True)
|
||||
alerts = fields.Text(compute='_compute_alerts_get', string="Alerts")
|
||||
previous_order_ids = fields.Many2many('lunch.order.line', compute='_compute_previous_order_ids',
|
||||
default=lambda self: self._default_previous_order_ids())
|
||||
company_id = fields.Many2one('res.company', related='user_id.company_id', store=True)
|
||||
currency_id = fields.Many2one('res.currency', related='company_id.currency_id', readonly=True, store=True)
|
||||
cash_move_balance = fields.Monetary(compute='_compute_cash_move_balance', multi='cash_move_balance')
|
||||
balance_visible = fields.Boolean(compute='_compute_cash_move_balance', multi='cash_move_balance')
|
||||
previous_order_ids = fields.Many2many('lunch.order.line', compute='_compute_previous_order')
|
||||
previous_order_widget = fields.Text(compute='_compute_previous_order')
|
||||
|
||||
@api.one
|
||||
@api.depends('order_line_ids')
|
||||
@@ -74,9 +75,35 @@ class LunchOrder(models.Model):
|
||||
if self.state == 'new':
|
||||
self.alerts = alert_msg and '\n'.join(alert_msg) or False
|
||||
|
||||
@api.depends('user_id')
|
||||
def _compute_previous_order_ids(self):
|
||||
self.previous_order_ids = self._default_previous_order_ids()
|
||||
@api.multi
|
||||
@api.depends('user_id', 'state')
|
||||
def _compute_previous_order(self):
|
||||
self.ensure_one()
|
||||
self.previous_order_widget = json.dumps(False)
|
||||
|
||||
prev_order = self.env['lunch.order.line'].search([('user_id', '=', self.env.uid), ('product_id.active', '!=', False)], limit=20, order='id desc')
|
||||
# If we use prev_order.ids, we will have duplicates (identical orders).
|
||||
# Therefore, this following part removes duplicates based on product_id and note.
|
||||
self.previous_order_ids = {
|
||||
(order.product_id, order.note): order.id
|
||||
for order in prev_order
|
||||
}.values()
|
||||
|
||||
if self.previous_order_ids:
|
||||
lunch_data = {}
|
||||
for line in self.previous_order_ids:
|
||||
lunch_data[line.id] = {
|
||||
'line_id': line.id,
|
||||
'product_id': line.product_id.id,
|
||||
'product_name': line.product_id.name,
|
||||
'supplier': line.supplier.name,
|
||||
'note': line.note,
|
||||
'price': line.price,
|
||||
'currency': line.currency_id.symbol,
|
||||
'digits': [69, line.currency_id.decimal_places],
|
||||
'position': line.currency_id.position,
|
||||
}
|
||||
self.previous_order_widget = json.dumps(lunch_data)
|
||||
|
||||
@api.one
|
||||
@api.depends('user_id')
|
||||
|
||||
@@ -1,75 +1,56 @@
|
||||
odoo.define('lunch.form_widgets', function (require) {
|
||||
odoo.define('lunch.previous_orders', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var form_common = require('web.form_common');
|
||||
var form_widgets = require('web.form_widgets');
|
||||
var form_relational = require('web.form_relational');
|
||||
var _t = core._t;
|
||||
var formats = require('web.formats');
|
||||
var Model = require('web.Model');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var LunchPreviousOrdersWidget = form_relational.AbstractManyField.extend(form_common.ReinitializeWidgetMixin, {
|
||||
className: 'row o_lunch_last_orders',
|
||||
var LunchPreviousOrdersWidget = form_common.AbstractField.extend({
|
||||
events: {
|
||||
'click .o_add_button': 'set_order_line',
|
||||
},
|
||||
init: function(field_manager, node) {
|
||||
this._super.apply(this, arguments);
|
||||
this.lunch_data = {};
|
||||
this.fields_to_read = ['product_id', 'supplier', 'note', 'price', 'category_id', 'currency_id'];
|
||||
this.monetary = new form_widgets.FieldMonetary(field_manager, node); // create instance to use format_value
|
||||
this.monetary.__edispatcherRegisteredEvents = []; // remove all bind events
|
||||
},
|
||||
fetch_value: function(){
|
||||
var self = this;
|
||||
return this.dataset.read_ids(this.get('value'), this.fields_to_read)
|
||||
.then(function(data) {
|
||||
_.each(data, function(order) {
|
||||
self.lunch_data[order['id']] = order;
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
get_line_value: function(id) {
|
||||
var data = _.clone(this.lunch_data[id]);
|
||||
if (typeof this.lunch_data[id]['product_id'][0] != 'undefined'){
|
||||
data['product_id'] = this.lunch_data[id]['product_id'][0];
|
||||
}
|
||||
if (typeof this.lunch_data[id]['supplier'][0] != 'undefined'){
|
||||
data['supplier'] = this.lunch_data[id]['supplier'][0];
|
||||
}
|
||||
if (typeof this.lunch_data[id]['category_id'][0] != 'undefined'){
|
||||
data['category_id'] = this.lunch_data[id]['category_id'][0];
|
||||
}
|
||||
return data;
|
||||
},
|
||||
set_order_line: function(event) {
|
||||
var data = this.get_line_value(parseInt($(event.currentTarget).data('id')));
|
||||
var order_line_ids = this.field_manager.fields.order_line_ids;
|
||||
order_line_ids.data_create(data);
|
||||
order_line_ids.reload_current_view();
|
||||
'click .o_add_button': 'add_order_line',
|
||||
},
|
||||
render_value: function() {
|
||||
var self = this;
|
||||
return this.fetch_value().then(function(data) {
|
||||
if (_.isEmpty(data)) {
|
||||
return self.$el.html(QWeb.render("lunch_order_widget_no_previous_order"));
|
||||
this.lunch_data = JSON.parse(this.get('value'));
|
||||
if (this.lunch_data !== false) {
|
||||
// Similar to format_value of FieldMonetary
|
||||
_.each(this.lunch_data, function(k, v) {
|
||||
k.price_format = formats.format_value(k.price, {type: "float", digits: k.digits});
|
||||
});
|
||||
|
||||
// Group data by supplier for display
|
||||
var categories = _.groupBy(this.lunch_data, function(p) {
|
||||
return p['supplier'];
|
||||
});
|
||||
this.$el.html(QWeb.render('LunchPreviousOrdersWidgetList', {'categories': categories}));
|
||||
} else {
|
||||
return this.$el.html(QWeb.render('LunchPreviousOrdersWidgetNoOrder'));
|
||||
}
|
||||
},
|
||||
add_order_line: function(event) {
|
||||
// Get order details from line
|
||||
var line_id = parseInt($(event.currentTarget).data('id'));
|
||||
if (!line_id) {
|
||||
return;
|
||||
}
|
||||
var values = {
|
||||
'product_id': this.lunch_data[line_id].product_id,
|
||||
'note': this.lunch_data[line_id].note,
|
||||
'price': this.lunch_data[line_id].price,
|
||||
}
|
||||
|
||||
// Create new order line and reload view
|
||||
var order_line_ids = this.field_manager.fields.order_line_ids;
|
||||
order_line_ids.data_create(values)
|
||||
.then(function (p) {
|
||||
order_line_ids.reload_current_view();
|
||||
}
|
||||
var categories = _.groupBy(data,function(data1){return data1['supplier'][1];});
|
||||
return self.$el.html(QWeb.render("lunch_order_widget_previous_orders_list", {'widget': self, 'categories': categories}));
|
||||
});
|
||||
},
|
||||
destroy: function() {
|
||||
this.monetary.destroy();
|
||||
this._super();
|
||||
},
|
||||
is_false: function() {
|
||||
return false;
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
core.form_widget_registry.add('previous_order', LunchPreviousOrdersWidget);
|
||||
|
||||
return LunchPreviousOrdersWidget;
|
||||
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
width: 100%;
|
||||
|
||||
.o_lunch_vignette {
|
||||
.clearfix();
|
||||
padding: 5px 0;
|
||||
|
||||
+ .o_lunch_vignette {
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates>
|
||||
<div t-name="lunch_order_widget_no_previous_order" class="col-md-12">
|
||||
<div t-name="LunchPreviousOrdersWidgetNoOrder" class="col-md-12">
|
||||
<h3>This is the first time you order a meal</h3>
|
||||
<p class="text-muted">Select a product and put your order comments on the note.</p>
|
||||
<p class="text-muted">Your favorite meals will be created based on your last orders.</p>
|
||||
<p class="text-muted">Don't forget the alerts displayed in the reddish area</p>
|
||||
</div>
|
||||
<t t-name="lunch_order_widget_previous_orders_list">
|
||||
<div t-foreach="categories" t-as="product_category" class="col-sm-4">
|
||||
<h3><t t-esc="product_category"/></h3>
|
||||
<div t-foreach='categories[product_category]' t-as='product' class="o_lunch_vignette">
|
||||
<button type="button" class="pull-right o_add_button oe_edit_only oe_link" t-att-data-id="product.id">
|
||||
<t t-name="LunchPreviousOrdersWidgetList">
|
||||
<div t-foreach="categories" t-as="supplier" class="col-md-4">
|
||||
<h3><t t-esc="supplier"/></h3>
|
||||
<div t-foreach='categories[supplier]' t-as='order' class="o_lunch_vignette">
|
||||
<button type="button" class="pull-right o_add_button oe_edit_only oe_link" t-att-data-id="order.line_id">
|
||||
<span class="fa fa-plus-square"></span>
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<div class="o_lunch_text">
|
||||
<t t-esc="product.product_id[1]"/>
|
||||
<div>
|
||||
<t t-esc="order.product_name"/>
|
||||
<span class="badge">
|
||||
<t t-esc="widget.monetary.format_value(product.price)"/> <t t-esc="product.currency_id[1]"/>
|
||||
<t t-if="order.position === 'before'"><t t-esc="order.currency"/></t>
|
||||
<span class="o_lunch_price"><t t-esc="order.price_format"></t></span>
|
||||
<t t-if="order.position === 'after'"><t t-esc="order.currency"/></t>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted"><t t-if="product.note != false" t-esc="product.note"/></div>
|
||||
<div class="text-muted">
|
||||
<t t-if="order.note != false" t-esc="order.note"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -377,7 +377,7 @@
|
||||
</group>
|
||||
|
||||
<div>
|
||||
<field name='previous_order_ids' widget='previous_order'/>
|
||||
<field name='previous_order_widget' widget='previous_order' class='o_lunch_last_orders'/>
|
||||
</div>
|
||||
|
||||
<separator string='Select your order'/>
|
||||
|
||||
Reference in New Issue
Block a user