[FIX] lunch: adapt the code to new views

We also adapt the code to comply to the new guidelines and we have
added some tests.
This commit is contained in:
Martin Geubelle
2017-04-19 17:49:34 +02:00
parent 3445597940
commit 90d6573579
5 changed files with 240 additions and 76 deletions
+1 -3
View File
@@ -99,9 +99,7 @@ class LunchOrder(models.Model):
'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,
'currency_id': line.currency_id.id,
}
self.previous_order_widget = json.dumps(lunch_data)
+76 -63
View File
@@ -1,81 +1,94 @@
odoo.define('lunch.previous_orders', function (require) {
"use strict";
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var field_utils = require('web.field_utils');
var field_registry = require('web.field_registry');
var relational_fields = require('web.relational_fields');
var field_utils = require('web.field_utils');
var QWeb = core.qweb;
var FieldMany2Many = relational_fields.FieldMany2Many;
var LunchPreviousOrdersWidget = FieldMany2Many.extend({
className: 'row o_lunch_last_orders',
var LunchPreviousOrdersWidget = AbstractField.extend({
events: {
'click .o_add_button': 'set_order_line',
'click .o_add_button': '_onAddOrder',
},
supported_field_types: [],
init: function() {
supportedFieldTypes: ['one2many'],
/**
* @override
*/
init: function () {
this._super.apply(this, arguments);
this.lunch_data = {};
this.fields_to_read = ['product_id', 'supplier', 'note', 'price', 'category_id', 'currency_id'];
this.format_value = function (value) {
var options = _.extend({}, this.nodeOptions, { data: this.recordData });
return field_utils.format.monetary(value, this.field, options);
this.lunchData = JSON.parse(this.value);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Used by the widget to render the previous order price like a monetary.
*
* @private
* @param {Object} order
* @returns {string} the monetary formatting of order price
*/
_formatValue: function (order) {
var options = _.extend({}, this.nodeOptions, order);
return field_utils.format.monetary(order.price, this.field, options);
},
/**
* @private
* @override
*/
_render: function () {
if (this.lunchData !== false) {
// group data by supplier for display
var categories = _.groupBy(this.lunchData, 'supplier');
this.$el.html(QWeb.render('LunchPreviousOrdersWidgetList', {
formatValue: this._formatValue.bind(this),
categories: categories,
}));
} else {
return this.$el.html(QWeb.render('LunchPreviousOrdersWidgetNoOrder'));
}
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
* @param {MouseEvent} event
*/
_onAddOrder: function (event) {
// Get order details from line
var lineID = parseInt($(event.currentTarget).data('id'));
if (!lineID) {
return;
}
var values = {
product_id: {
id: this.lunchData[lineID].product_id,
display_name: this.lunchData[lineID].product_name,
},
note: this.lunchData[lineID].note,
price: this.lunchData[lineID].price,
};
},
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() {
// FIXME: This is the true functionality of this widget in edit mode
// 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();
},
render: function() {
var self = this;
// Fetch values
// FIXME: this might be replaced when we implement a way for widgets
// to declare which fields they need from the relational data
this.trigger_up('perform_model_rpc', {
model: 'lunch.order.line',
method: 'read',
args: [
this.value,
this.fields_to_read
],
on_success: function (orders) {
if (_.isEmpty(orders)) {
self.$el.html(QWeb.render("LunchPreviousOrdersWidgetNoOrder"));
} else {
_.each(orders, function(order) {
self.lunch_data[order.id] = order;
});
var categories = _.groupBy(orders, function(o){ return o.supplier[1]; });
return self.$el.html(QWeb.render("LunchPreviousOrdersWidgetList", {'widget': self, 'categories': categories}));
}
}
// create a new order line
this.trigger_up('field_changed', {
dataPointID: this.dataPointID,
changes: {
order_line_ids: {
operation: 'CREATE',
data: values,
},
},
});
},
has_no_value: function() {
return false;
},
});
field_registry.add('previous_order', LunchPreviousOrdersWidget);
return LunchPreviousOrdersWidget;
});
+12 -10
View File
@@ -7,20 +7,22 @@
<p class="text-muted">Don't forget the alerts displayed in the reddish area</p>
</div>
<t t-name="LunchPreviousOrdersWidgetList">
<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">
<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">
<div class="badge pull-right">
<t t-esc="widget.format_value(product.price)"/> <t t-esc="product.currency_id[1]"/>
</div>
<t t-esc="product.product_id[1]"/>
<div>
<t t-esc="order.product_name"/>
<span class="badge pull-right">
<span class="o_lunch_price" t-raw="formatValue(order)"/>
</span>
</div>
<div class="text-muted">
<t t-if="order.note != false" t-esc="order.note"/>
</div>
<div class="text-muted"><t t-if="product.note != false" t-esc="product.note"/></div>
</div>
</div>
</t>
+145
View File
@@ -0,0 +1,145 @@
odoo.define('lunch.tests', function (require) {
"use strict";
var FormView = require('web.FormView');
var testUtils = require('web.test_utils');
var createView = testUtils.createView;
QUnit.module('lunch', {
beforeEach: function () {
this.data = {
order: {
fields: {
previous_order_widget: {type: 'text'},
order_line_ids: {type: 'many2many', relation: 'order_line'}
},
records: [{
id: 1,
name: 'coucou',
}, {
id: 2,
name: 'coucou',
}, {
id: 11,
}],
},
order_line: {
fields: {
product_id: {type: 'many2one', relation: 'product'},
note: {type: 'text'},
price: {type: 'float'},
},
},
supplier: {
fields: {},
records: [{
id: 1,
display_name: "Coin Gourmant",
}, {
id: 2,
display_name: "Pizza Inn",
}]
},
product: {
fields: {},
records: [{
id: 1,
name: 'Pizza Margherita',
}],
}
};
},
}, function () {
QUnit.test("empty previous_order widget", function (assert) {
assert.expect(2);
var form = createView({
View: FormView,
arch: '<form>' +
'<sheet>' +
'<field name="previous_order_widget" widget="previous_order"/>' +
'<field name="order_line_ids"/>' +
'</sheet>' +
'</form>',
data: this.data,
model: 'order',
archs: {
"order_line,false,list": '<tree string="Orders">' +
'<field name="product_id"/>' +
'<field name="note"/>' +
'<field name="price"/>' +
'</tree>',
},
});
var widgetText = form.$('.o_form_field[name="previous_order_widget"]').text();
assert.ok(widgetText.indexOf('This is the first time you order a meal') !== -1,
"the widget should display its no content text");
assert.strictEqual(form.$('.o_lunch_vignette').length, 0,
"there should be no vignette");
form.destroy();
});
QUnit.test("add an order line with previous_order widget", function (assert) {
assert.expect(4);
var form = createView({
View: FormView,
arch: '<form>' +
'<sheet>' +
'<field name="previous_order_widget" widget="previous_order"/>' +
'<field name="order_line_ids"/>' +
'</sheet>' +
'</form>',
data: this.data,
model: 'order',
mockRPC: function (route, args) {
if (args.method === 'default_get') {
return $.when({
previous_order_widget: '{' +
'"8": {' +
'"note": "coucou",' +
'"line_id": 8,' +
'"digits": [69, 2],' +
'"product_id": 1,' +
'"currency": "$",' +
'"supplier": "Pizza Inn",' +
'"position": "before",' +
'"price": 6.9,' +
'"product_name": "Pizza Margherita"' +
'}' +
'}'
});
}
return this._super.apply(this, arguments);
},
archs: {
"order_line,false,list": '<tree string="Orders">' +
'<field name="product_id"/>' +
'<field name="note"/>' +
'<field name="price"/>' +
'</tree>',
},
});
assert.strictEqual(form.$('.o_list_view tr.o_data_row').length, 0,
"there should be no row in the one2many list");
assert.strictEqual(form.$('.o_lunch_vignette').length, 1,
"there should be a vignette");
// add an order
form.$('.o_lunch_vignette .o_add_button').click();
assert.strictEqual(form.$('.o_list_view tr.o_data_row').length, 1,
"there should be one new row in the one2many list");
assert.strictEqual(form.$('.o_list_view tr.o_data_row').text(), "Pizza Margheritacoucou6.90",
"the line should contain the correct data");
form.destroy();
});
});
});
+6
View File
@@ -6,4 +6,10 @@
<script type="text/javascript" src="/lunch/static/src/js/lunch.js"></script>
</xpath>
</template>
<template id="qunit_suite" name="lunch tests" inherit_id="web.qunit_suite">
<xpath expr="//t[@t-set='head']" position="inside">
<script type="text/javascript" src="/lunch/static/tests/lunch_tests.js"/>
</xpath>
</template>
</odoo>