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