diff --git a/addons/web/static/src/js/views/abstract_model.js b/addons/web/static/src/js/views/abstract_model.js
index 27d13a12b06..4ea6b217e65 100644
--- a/addons/web/static/src/js/views/abstract_model.js
+++ b/addons/web/static/src/js/views/abstract_model.js
@@ -15,6 +15,7 @@ odoo.define('web.AbstractModel', function (require) {
*/
var Class = require('web.Class');
+var fieldUtils = require('web.field_utils');
var mixins = require('web.mixins');
var ServicesMixin = require('web.ServicesMixin');
@@ -63,6 +64,30 @@ var AbstractModel = Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
reload: function (params) {
return $.when();
},
+ /**
+ * Processes date(time) and selection field values sent by the server.
+ * Converts data(time) values to moment instances.
+ * Converts false values of selection fields to 0 if 0 is a valid key,
+ * because the server doesn't make a distinction between false and 0, and
+ * always sends false when value is 0.
+ *
+ * @param {Object} field the field description
+ * @param {*} value
+ * @returns {*} the processed value
+ */
+ _parseServerValue: function (field, value) {
+ if (field.type === 'date' || field.type === 'datetime') {
+ // process date(time): convert into a moment instance
+ value = fieldUtils.parse[field.type](value, field, {isUTC: true});
+ } else if (field.type === 'selection' && value === false) {
+ // process selection: convert false to 0, if 0 is a valid key
+ var hasKey0 = _.find(field.selection, function (option) {
+ return option[0] === 0;
+ });
+ value = hasKey0 ? 0 : value;
+ }
+ return value;
+ },
});
return AbstractModel;
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index c95f829af71..eead1b0aaed 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -87,7 +87,6 @@ var concurrency = require('web.concurrency');
var Context = require('web.Context');
var core = require('web.core');
var Domain = require('web.Domain');
-var fieldUtils = require('web.field_utils');
var session = require('web.session');
var _t = core._t;
@@ -2946,30 +2945,6 @@ var BasicModel = AbstractModel.extend({
}
});
},
- /**
- * Processes date(time) and selection field values sent by the server.
- * Converts data(time) values to moment instances.
- * Converts false values of selection fields to 0 if 0 is a valid key,
- * because the server doesn't make a distinction between false and 0, and
- * always sends false when value is 0.
- *
- * @param {Object} field the field description
- * @param {*} value
- * @returns {*} the processed value
- */
- _parseServerValue: function (field, value) {
- if (field.type === 'date' || field.type === 'datetime') {
- // process date(time): convert into a moment instance
- value = fieldUtils.parse[field.type](value, field, {isUTC: true});
- } else if (field.type === 'selection' && value === false) {
- // process selection: convert false to 0, if 0 is a valid key
- var hasKey0 = _.find(field.selection, function (option) {
- return option[0] === 0;
- });
- value = hasKey0 ? 0 : value;
- }
- return value;
- },
/**
* This method is quite important: it is supposed to perform the /onchange
* rpc and apply the result.
diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index ded7938605f..73868a93fdb 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -406,12 +406,13 @@ return AbstractModel.extend({
});
}
return eventsDef.then(function (events) {
- self.data.data = _.map(events, self._recordToCalendarEvent.bind(self));
- return $.when(
- self._loadColors(self.data, self.data.data),
- self._loadRecordsToFilters(self.data, self.data.data)
- );
- });
+ self._parseServerData(events);
+ self.data.data = _.map(events, self._recordToCalendarEvent.bind(self));
+ return $.when(
+ self._loadColors(self.data, self.data.data),
+ self._loadRecordsToFilters(self.data, self.data.data)
+ );
+ });
});
},
/**
@@ -566,11 +567,24 @@ return AbstractModel.extend({
if (filter.filters.length && (filter.filters[0].avatar_model in to_read)) {
_.each(filter.filters, function (f) {
f.label = to_read[f.avatar_model][f.value];
- });
+ });
}
});
});
},
+ /**
+ * parse the server values to javascript framwork
+ *
+ * @param {Object} data the server data to parse
+ */
+ _parseServerData: function (data) {
+ var self = this;
+ _.each(data, function(event) {
+ _.each(self.fieldNames, function (fieldName) {
+ event[fieldName] = self._parseServerValue(self.fields[fieldName], event[fieldName]);
+ });
+ });
+ },
/**
* Transform OpenERP event object to fullcalendar event object
*/
@@ -583,11 +597,11 @@ return AbstractModel.extend({
attendees = [];
if (!all_day) {
- date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start]);
- date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop]) : null;
+ date_start = evt[this.mapping.date_start].clone();
+ date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone() : null;
} else {
- date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start].split(' ')[0]);
- date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop].split(' ')[0]) : null;
+ date_start = evt[this.mapping.date_start].clone().startOf('day');
+ date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone().startOf('day') : null;
}
if (!date_stop && date_delay) {
@@ -605,8 +619,8 @@ return AbstractModel.extend({
'record': evt,
'start': date_start,
'end': date_stop,
- 'r_start':date_start.clone(),
- 'r_end':date_stop.clone(),
+ 'r_start': date_start,
+ 'r_end': date_stop,
'title': the_title,
'allDay': this.mapping.all_day && evt[this.mapping.all_day] || false,
'id': evt.id,
diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js
index 011843eefee..21e4e8c26a7 100644
--- a/addons/web/static/tests/views/calendar_tests.js
+++ b/addons/web/static/tests/views/calendar_tests.js
@@ -3,6 +3,7 @@ odoo.define('web.calendar_tests', function (require) {
var CalendarView = require('web.CalendarView');
var CalendarRenderer = require('web.CalendarRenderer');
+var fieldUtils = require('web.field_utils');
var testUtils = require('web.test_utils');
var session = require('web.session');
@@ -431,6 +432,7 @@ QUnit.module('Views', {
'mode="week" '+
'readonly_form_view_id="1">'+
''+
+ ''+
'',
archs: archs,
viewOptions: {
@@ -478,14 +480,14 @@ QUnit.module('Views', {
$('.modal button.btn:contains(Create)').trigger('click');
var $newevent = calendar.$('.fc-event:contains(new event)');
- assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "08:00-10:00newevent",
+ assert.strictEqual($newevent.text().replace(/[\s\n\r]+/g, ''), "08:00-10:00newevent12/13/201608:00:00",
"should display the new event with time and title");
assert.deepEqual($newevent.data('fcSeg').event.record,
{
display_name: "new event",
- start: "2016-12-13 06:00:00",
- stop: "2016-12-13 08:00:00",
+ start: fieldUtils.parse.datetime("2016-12-13 06:00:00", this.data.event.fields.start, {isUTC: true}),
+ stop: fieldUtils.parse.datetime("2016-12-13 08:00:00", this.data.event.fields.stop, {isUTC: true}),
allday: false,
name: "new event",
id: 1
@@ -616,8 +618,8 @@ QUnit.module('Views', {
assert.deepEqual($newevent.data('fcSeg').event.record,
{
display_name: "new event",
- start: "2016-12-13 06:00:00",
- stop: "2016-12-13 08:00:00",
+ start: fieldUtils.parse.datetime("2016-12-13 06:00:00", this.data.event.fields.start, {isUTC: true}),
+ stop: fieldUtils.parse.datetime("2016-12-13 08:00:00", this.data.event.fields.stop, {isUTC: true}),
allday: false,
name: "new event",
id: 1
@@ -691,8 +693,8 @@ QUnit.module('Views', {
assert.deepEqual($newevent.data('fcSeg').event.record,
{
display_name: "new event",
- start: "2016-12-14 00:00:00",
- stop: "2016-12-15 00:00:00",
+ start: fieldUtils.parse.datetime("2016-12-14 00:00:00", this.data.event.fields.start, {isUTC: true}),
+ stop: fieldUtils.parse.datetime("2016-12-15 00:00:00", this.data.event.fields.stop, {isUTC: true}),
allday: true,
name: "new event",
id: 1