From 2ebe3076d2abbe2bef3ed7612af212f23382c0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 10 Mar 2015 08:45:02 +0100 Subject: [PATCH] [REF] hr: update to the new module system --- addons/hr/static/src/js/hr.js | 28 +- addons/hr/static/src/js/suggestions.js | 141 ++-- .../hr_attendance/static/src/js/attendance.js | 157 ++-- .../static/src/js/gamification.js | 41 +- .../static/src/js/job_position.js | 26 +- .../static/src/js/timesheet.js | 695 +++++++++--------- 6 files changed, 561 insertions(+), 527 deletions(-) diff --git a/addons/hr/static/src/js/hr.js b/addons/hr/static/src/js/hr.js index 90e37bd35b8..80b978e7fc9 100644 --- a/addons/hr/static/src/js/hr.js +++ b/addons/hr/static/src/js/hr.js @@ -1,14 +1,18 @@ -openerp.hr = function(openerp) { - "use strict"; +odoo.define('hr.hr', ['web_kanban.common'], function(require) { +"use strict"; - openerp.web_kanban.KanbanRecord.include({ - on_card_clicked: function() { - if (this.view.dataset.model === 'hr.department') { - this.$('.oe_kanban_department .oe_kanban_content a').first().click(); - } else { - this._super.apply(this, arguments); - } - }, - }); +var common = require('web_kanban.common'); + +common.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'hr.department') { + this.$('.oe_kanban_department .oe_kanban_content a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, +}); + + +}); -}; diff --git a/addons/hr/static/src/js/suggestions.js b/addons/hr/static/src/js/suggestions.js index 3bc37e71344..94df0a4ad7b 100644 --- a/addons/hr/static/src/js/suggestions.js +++ b/addons/hr/static/src/js/suggestions.js @@ -1,78 +1,83 @@ -openerp.hr = function(session) { - var _t = session.web._t; - var QWeb = session.web.qweb; +odoo.define('hr.suggestions', ['mail.mail', 'web.core', 'web.data', 'web.Widget'], function (require) { +"use strict"; - var suggestions = session.suggestions; - var removed_suggested_employee = session.suggestions.removed_suggested_employee = []; +var mail = require('mail.mail'); +var core = require('web.core'); +var data = require('web.data'); +var Widget = require('web.Widget'); - suggestions.Employees = session.web.Widget.extend({ - events: { - 'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion', - 'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion', - 'click .oe_suggestion_follow': 'follow_employee', - }, +var QWeb = core.qweb; - init: function () { - this._super(this, arguments); - this.hr_employee = new session.web.DataSetSearch(this, 'hr.employee'); - this.res_users = new session.web.DataSetSearch(this, 'res.users'); - this.employees = []; - }, +var removed_suggested_employee = []; - start: function () { - this._super.apply(this, arguments); - return this.fetch_suggested_employee(); - }, +var Employees = Widget.extend({ + events: { + 'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion', + 'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion', + 'click .oe_suggestion_follow': 'follow_employee', + }, - fetch_suggested_employee: function () { - var self = this; - var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) { - _(res).each(function (result) { - result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id}); - }); - self.employees = res; + init: function () { + this._super(this, arguments); + this.hr_employee = new data.DataSetSearch(this, 'hr.employee'); + this.res_users = new data.DataSetSearch(this, 'res.users'); + this.employees = []; + }, + + start: function () { + this._super.apply(this, arguments); + return this.fetch_suggested_employee(); + }, + + fetch_suggested_employee: function () { + var self = this; + var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) { + _(res).each(function (result) { + result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id}); }); - return $.when(employee).done(this.proxy('display_suggested_employees')); - }, + self.employees = res; + }); + return $.when(employee).done(this.proxy('display_suggested_employees')); + }, - display_suggested_employees: function () { - var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee'); - if (suggested_employees) { - suggested_employees.remove(); - } - if (this.employees.length === 0) { - return this.$el.empty(); - } - return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this})); - }, - - follow_employee: function (event) { - var self = this; - var employee_id = parseInt($(event.currentTarget).attr('id'), 10); - return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) { - self.fetch_suggested_employee(); - }); - }, - - remove_employee_suggestion: function (event) { - removed_suggested_employee.push($(event.currentTarget).attr('id')); - return this.fetch_suggested_employee(); - }, - - stop_employee_suggestion: function (event) { - var self = this; - return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) { - self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide(); - }); + display_suggested_employees: function () { + var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee'); + if (suggested_employees) { + suggested_employees.remove(); } - }); + if (this.employees.length === 0) { + return this.$el.empty(); + } + return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this})); + }, - session.mail.WallSidebar.include({ - start: function () { - this._super.apply(this, arguments); - var sug_employees = new suggestions.Employees(this); - return sug_employees.appendTo(this.$('.oe_suggestions_employees')); - }, - }); + follow_employee: function (event) { + var self = this; + var employee_id = parseInt($(event.currentTarget).attr('id'), 10); + return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) { + self.fetch_suggested_employee(); + }); + }, -}; + remove_employee_suggestion: function (event) { + removed_suggested_employee.push($(event.currentTarget).attr('id')); + return this.fetch_suggested_employee(); + }, + + stop_employee_suggestion: function (event) { + var self = this; + return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) { + self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide(); + }); + } +}); + +mail.WallSidebar.include({ + start: function () { + this._super.apply(this, arguments); + var sug_employees = new Employees(this); + return sug_employees.appendTo(this.$('.oe_suggestions_employees')); + }, +}); + +}); diff --git a/addons/hr_attendance/static/src/js/attendance.js b/addons/hr_attendance/static/src/js/attendance.js index 3ec2ca4709f..783728b7d79 100644 --- a/addons/hr_attendance/static/src/js/attendance.js +++ b/addons/hr_attendance/static/src/js/attendance.js @@ -1,79 +1,86 @@ +odoo.define('hr_attendance.hr_attendance', ['web.core', 'web.data', 'web.formats', 'web.Model', 'web.SystrayMenu', 'web.time', 'web.Widget'], function(require) { +"use strict"; -openerp.hr_attendance = function (instance) { - - var QWeb = instance.web.qweb; - var _t = instance.web._t; - var _lt = instance.web._lt; +var core = require('web.core'); +var data = require('web.data'); +var formats = require('web.formats'); +var Model = require('web.Model'); +var SystrayMenu = require('web.SystrayMenu'); +var time = require('web.time'); +var Widget = require('web.Widget'); - instance.hr_attendance.AttendanceSlider = instance.web.Widget.extend({ - template: 'AttendanceSlider', - init: function (parent) { - this._super(parent); - this.set({"signed_in": false}); - }, - start: function() { - var self = this; - var tmp = function() { - var $sign_in_out_icon = this.$('#oe_attendance_sign_in_out_icon'); - $sign_in_out_icon.toggleClass("fa-sign-in", ! this.get("signed_in")); - $sign_in_out_icon.toggleClass("fa-sign-out", this.get("signed_in")); - }; - this.on("change:signed_in", this, tmp); - _.bind(tmp, this)(); - this.$(".oe_attendance_sign_in_out").click(function(ev) { - ev.preventDefault(); - self.do_update_attendance(); - }); - this.$el.tooltip({ - title: function() { - var last_text = instance.web.format_value(self.last_sign, {type: "datetime"}); - var current_text = instance.web.format_value(new Date(), {type: "datetime"}); - var duration = self.last_sign ? $.timeago(self.last_sign) : "none"; - if (self.get("signed_in")) { - return _.str.sprintf(_t("Last sign in: %s,
%s.
Click to sign out."), last_text, duration); - } else { - return _.str.sprintf(_t("Click to Sign In at %s."), current_text); - } - }, - }); - return this.check_attendance(); - }, - do_update_attendance: function () { - var self = this; - var hr_employee = new instance.web.DataSet(self, 'hr.employee'); - hr_employee.call('attendance_action_change', [ - [self.employee.id] - ]).done(function (result) { - self.last_sign = new Date(); - self.set({"signed_in": ! self.get("signed_in")}); - }); - }, - check_attendance: function () { - var self = this; - self.employee = false; - this.$el.hide(); - var employee = new instance.web.DataSetSearch(self, 'hr.employee', self.session.user_context, [ - ['user_id', '=', self.session.uid] - ]); - return employee.read_slice(['id', 'name', 'state', 'last_sign', 'attendance_access']).then(function (res) { - if (_.isEmpty(res) ) - return; - if (res[0].attendance_access === false){ - return; +var _t = core._t; + +var AttendanceSlider = Widget.extend({ + template: 'AttendanceSlider', + init: function (parent) { + this._super(parent); + this.set({"signed_in": false}); + }, + start: function() { + var self = this; + var tmp = function() { + var $sign_in_out_icon = this.$('#oe_attendance_sign_in_out_icon'); + $sign_in_out_icon.toggleClass("fa-sign-in", ! this.get("signed_in")); + $sign_in_out_icon.toggleClass("fa-sign-out", this.get("signed_in")); + }; + this.on("change:signed_in", this, tmp); + _.bind(tmp, this)(); + this.$(".oe_attendance_sign_in_out").click(function(ev) { + ev.preventDefault(); + self.do_update_attendance(); + }); + this.$el.tooltip({ + title: function() { + var last_text = formats.format_value(self.last_sign, {type: "datetime"}); + var current_text = formats.format_value(new Date(), {type: "datetime"}); + var duration = self.last_sign ? $.timeago(self.last_sign) : "none"; + if (self.get("signed_in")) { + return _.str.sprintf(_t("Last sign in: %s,
%s.
Click to sign out."), last_text, duration); + } else { + return _.str.sprintf(_t("Click to Sign In at %s."), current_text); } - self.$el.show(); - self.employee = res[0]; - self.last_sign = instance.web.str_to_datetime(self.employee.last_sign); - self.set({"signed_in": self.employee.state !== "absent"}); - }); - }, - }); + }, + }); + return this.check_attendance(); + }, + do_update_attendance: function () { + var self = this; + var hr_employee = new data.DataSet(self, 'hr.employee'); + hr_employee.call('attendance_action_change', [ + [self.employee.id] + ]).done(function (result) { + self.last_sign = new Date(); + self.set({"signed_in": ! self.get("signed_in")}); + }); + }, + check_attendance: function () { + var self = this; + self.employee = false; + this.$el.hide(); + var employee = new data.DataSetSearch(self, 'hr.employee', self.session.user_context, [ + ['user_id', '=', self.session.uid] + ]); + return employee.read_slice(['id', 'name', 'state', 'last_sign', 'attendance_access']).then(function (res) { + if (_.isEmpty(res) ) + return; + if (res[0].attendance_access === false){ + return; + } + self.$el.show(); + self.employee = res[0]; + self.last_sign = time.str_to_datetime(self.employee.last_sign); + self.set({"signed_in": self.employee.state !== "absent"}); + }); + }, +}); - // Put the AttendanceSlider widget in the systray menu if the user is an employee - var Users = new instance.web.Model('res.users'); - Users.call('has_group', ['base.group_user']).done(function(is_employee) { - if (is_employee) { - instance.web.SystrayItems.push(instance.hr_attendance.AttendanceSlider); - } - }) -}; +// Put the AttendanceSlider widget in the systray menu if the user is an employee +var Users = new Model('res.users'); +Users.call('has_group', ['base.group_user']).done(function(is_employee) { + if (is_employee) { + SystrayMenu.Items.push(AttendanceSlider); + } +}); + +}); diff --git a/addons/hr_gamification/static/src/js/gamification.js b/addons/hr_gamification/static/src/js/gamification.js index a9126464a10..ad065ecfa23 100644 --- a/addons/hr_gamification/static/src/js/gamification.js +++ b/addons/hr_gamification/static/src/js/gamification.js @@ -1,19 +1,24 @@ -openerp.hr_gamification = function(instance) { - instance.web_kanban.KanbanRecord.include({ - on_card_clicked: function() { - if (this.view.dataset.model === 'gamification.badge.user') { - var action = { - type: 'ir.actions.act_window', - res_model: 'gamification.badge', - view_mode: 'form', - view_type: 'form,kanban,tree', - views: [[false, 'form']], - res_id: this.record.badge_id.raw_value[0] - }; - this.do_action(action); - } else { - this._super.apply(this, arguments); - } +odoo.define('hr_gamification.hr_gamification', ['web_kanban.common'], function(require) { +"use strict"; + +var common = require('web_kanban.common'); + +common.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'gamification.badge.user') { + var action = { + type: 'ir.actions.act_window', + res_model: 'gamification.badge', + view_mode: 'form', + view_type: 'form,kanban,tree', + views: [[false, 'form']], + res_id: this.record.badge_id.raw_value[0] + }; + this.do_action(action); + } else { + this._super.apply(this, arguments); } - }); -}; + } +}); + +}); diff --git a/addons/hr_recruitment/static/src/js/job_position.js b/addons/hr_recruitment/static/src/js/job_position.js index 43150117115..55361fdef2a 100644 --- a/addons/hr_recruitment/static/src/js/job_position.js +++ b/addons/hr_recruitment/static/src/js/job_position.js @@ -1,14 +1,16 @@ -openerp.hr_recruitment = function (openerp) { - "use strict"; +odoo.define('hr_recruitment.hr_recruitment', ['web_kanban.common'], function(require) { +"use strict"; - openerp.web_kanban.KanbanRecord.include({ - on_card_clicked: function() { - if (this.view.dataset.model === 'hr.job') { - this.$('.oe_applications a').first().click(); - } else { - this._super.apply(this, arguments); - } - }, - }); +var common = require('web_kanban.common'); -}; +common.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'hr.job') { + this.$('.oe_applications a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, +}); + +}); diff --git a/addons/hr_timesheet_sheet/static/src/js/timesheet.js b/addons/hr_timesheet_sheet/static/src/js/timesheet.js index 400e4c2214a..ef3eb5c4f0a 100644 --- a/addons/hr_timesheet_sheet/static/src/js/timesheet.js +++ b/addons/hr_timesheet_sheet/static/src/js/timesheet.js @@ -1,357 +1,368 @@ +odoo.define('hr_timesheet_sheet.sheet', ['web.core', 'web.data', 'web.form_common', 'web.formats', 'web.Model', 'web.time', 'web.utils'], function (require) { +"use strict"; -openerp.hr_timesheet_sheet = function(instance) { - var QWeb = instance.web.qweb; - var _t = instance.web._t; +var core = require('web.core'); +var data = require('web.data'); +var form_common = require('web.form_common'); +var formats = require('web.formats'); +var Model = require('web.Model'); +var time = require('web.time'); +var utils = require('web.utils'); - instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, { - events: { - "click .oe_timesheet_weekly_account a": "go_to", - }, - ignore_fields: function() { - return ['line_id']; - }, - init: function() { - this._super.apply(this, arguments); - var self = this; - this.set({ - sheets: [], - date_to: false, - date_from: false, - }); - this.updating = false; - this.defs = []; - this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets); - this.field_manager.on("field_changed:date_from", this, function() { - this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))}); - }); - this.field_manager.on("field_changed:date_to", this, function() { - this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))}); - }); - this.field_manager.on("field_changed:user_id", this, function() { - this.set({"user_id": this.field_manager.get_field_value("user_id")}); - }); - this.on("change:sheets", this, this.update_sheets); - this.res_o2m_drop = new instance.web.DropMisordered(); - this.render_drop = new instance.web.DropMisordered(); - this.description_line = _t("/"); - // Original save function is overwritten in order to wait all running deferreds to be done before actually applying the save. - this.view.original_save = _.bind(this.view.save, this.view); - this.view.save = function(prepend_on_create){ - self.prepend_on_create = prepend_on_create; - return $.when.apply($, self.defs).then(function(){ - return self.view.original_save(self.prepend_on_create); - }); - }; - }, - go_to: function(event) { - var id = JSON.parse($(event.target).data("id")); - this.do_action({ - type: 'ir.actions.act_window', - res_model: "account.analytic.account", - res_id: id, - views: [[false, 'form']], - target: 'current' - }); - }, - query_sheets: function() { - var self = this; - if (self.updating) - return; - var commands = this.field_manager.get_field_value("timesheet_ids"); - this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [], - new instance.web.CompoundContext()])) - .done(function(result) { - self.querying = true; - self.set({sheets: result}); - self.querying = false; - }); - }, - update_sheets: function() { - var self = this; - if (self.querying) - return; - self.updating = true; - self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() { - self.updating = false; - }); - }, - initialize_field: function() { - instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this); - var self = this; - self.on("change:sheets", self, self.initialize_content); - self.on("change:date_to", self, self.initialize_content); - self.on("change:date_from", self, self.initialize_content); - self.on("change:user_id", self, self.initialize_content); - }, - initialize_content: function() { - var self = this; - if (self.setting) - return; - // don't render anything until we have date_to and date_from - if (!self.get("date_to") || !self.get("date_from")) - return; - this.destroy_content(); +var QWeb = core.qweb; +var _t = core._t; - // it's important to use those vars to avoid race conditions - var dates; - var accounts; - var account_names; - var default_get; - return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [ - ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'], - new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) { - default_get = result; - // calculating dates - dates = []; - var start = self.get("date_from"); - var end = self.get("date_to"); - while (start <= end) { - dates.push(start); - var m_start = moment(start).add(1,'days'); - start = m_start.toDate(); - } - // group by account - accounts = _(self.get("sheets")).chain() - .map(function(el) { - // much simpler to use only the id in all cases - if (typeof(el.account_id) === "object") - el.account_id = el.account_id[0]; - return el; - }) - .groupBy("account_id").value(); - var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) }); - - return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids, - new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) { - accounts = _(accounts).chain().map(function(lines, account_id) { - account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {}); - // group by days - account_id = account_id === "false" ? false : Number(account_id); - var index = _.groupBy(lines, "date"); - var days = _.map(dates, function(date) { - var day = {day: date, lines: index[instance.web.date_to_str(date)] || []}; - // add line where we will insert/remove hours - var to_add = _.find(day.lines, function(line) { return line.name === self.description_line }); - if (to_add) { - day.lines = _.without(day.lines, to_add); - day.lines.unshift(to_add); - } else { - day.lines.unshift(_.extend(_.clone(account_defaults), { - name: self.description_line, - unit_amount: 0, - date: instance.web.date_to_str(date), - account_id: account_id, - })); - } - return day; - }); - return {account: account_id, days: days, account_defaults: account_defaults}; - }).value(); - - // we need the name_get of the analytic accounts - return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"), - new instance.web.CompoundContext()]).then(function(result) { - account_names = {}; - _.each(result, function(el) { - account_names[el[0]] = el[1]; - }); - accounts = _.sortBy(accounts, function(el) { - return account_names[el.account]; - }); - });; - }); - })).then(function(result) { - // we put all the gathered data in self, then we render - self.dates = dates; - self.accounts = accounts; - self.account_names = account_names; - self.default_get = default_get; - //real rendering - self.display_data(); +var WeeklyTimesheet = form_common.FormWidget.extend(form_common.ReinitializeWidgetMixin, { + events: { + "click .oe_timesheet_weekly_account a": "go_to", + }, + ignore_fields: function() { + return ['line_id']; + }, + init: function() { + this._super.apply(this, arguments); + var self = this; + this.set({ + sheets: [], + date_to: false, + date_from: false, + }); + this.updating = false; + this.defs = []; + this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets); + this.field_manager.on("field_changed:date_from", this, function() { + this.set({"date_from": time.str_to_date(this.field_manager.get_field_value("date_from"))}); + }); + this.field_manager.on("field_changed:date_to", this, function() { + this.set({"date_to": time.str_to_date(this.field_manager.get_field_value("date_to"))}); + }); + this.field_manager.on("field_changed:user_id", this, function() { + this.set({"user_id": this.field_manager.get_field_value("user_id")}); + }); + this.on("change:sheets", this, this.update_sheets); + this.res_o2m_drop = new utils.DropMisordered(); + this.render_drop = new utils.DropMisordered(); + this.description_line = _t("/"); + // Original save function is overwritten in order to wait all running deferreds to be done before actually applying the save. + this.view.original_save = _.bind(this.view.save, this.view); + this.view.save = function(prepend_on_create){ + self.prepend_on_create = prepend_on_create; + return $.when.apply($, self.defs).then(function(){ + return self.view.original_save(self.prepend_on_create); }); - }, - destroy_content: function() { - if (this.dfm) { - this.dfm.destroy(); - this.dfm = undefined; + }; + }, + go_to: function(event) { + var id = JSON.parse($(event.target).data("id")); + this.do_action({ + type: 'ir.actions.act_window', + res_model: "account.analytic.account", + res_id: id, + views: [[false, 'form']], + target: 'current' + }); + }, + query_sheets: function() { + var self = this; + if (self.updating) + return; + var commands = this.field_manager.get_field_value("timesheet_ids"); + this.res_o2m_drop.add(new Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [], + new data.CompoundContext()])) + .done(function(result) { + self.querying = true; + self.set({sheets: result}); + self.querying = false; + }); + }, + update_sheets: function() { + var self = this; + if (self.querying) + return; + self.updating = true; + self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() { + self.updating = false; + }); + }, + initialize_field: function() { + form_common.ReinitializeWidgetMixin.initialize_field.call(this); + var self = this; + self.on("change:sheets", self, self.initialize_content); + self.on("change:date_to", self, self.initialize_content); + self.on("change:date_from", self, self.initialize_content); + self.on("change:user_id", self, self.initialize_content); + }, + initialize_content: function() { + var self = this; + if (self.setting) + return; + // don't render anything until we have date_to and date_from + if (!self.get("date_to") || !self.get("date_from")) + return; + this.destroy_content(); + + // it's important to use those vars to avoid race conditions + var dates; + var accounts; + var account_names; + var default_get; + return this.render_drop.add(new Model("hr.analytic.timesheet").call("default_get", [ + ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'], + new data.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) { + default_get = result; + // calculating dates + dates = []; + var start = self.get("date_from"); + var end = self.get("date_to"); + while (start <= end) { + dates.push(start); + var m_start = moment(start).add(1,'days'); + start = m_start.toDate(); } - }, - is_valid_value:function(value){ - var split_value = value.split(":"); - var valid_value = true; - if (split_value.length > 2) - return false; - _.detect(split_value,function(num){ - if(isNaN(num)){ - valid_value = false; + // group by account + accounts = _(self.get("sheets")).chain() + .map(function(el) { + // much simpler to use only the id in all cases + if (typeof(el.account_id) === "object") + el.account_id = el.account_id[0]; + return el; + }) + .groupBy("account_id").value(); + + var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el); }); + + return new Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids, + new data.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) { + accounts = _(accounts).chain().map(function(lines, account_id) { + var account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {}); + // group by days + account_id = account_id === "false" ? false : Number(account_id); + var index = _.groupBy(lines, "date"); + var days = _.map(dates, function(date) { + var day = {day: date, lines: index[time.date_to_str(date)] || []}; + // add line where we will insert/remove hours + var to_add = _.find(day.lines, function(line) { return line.name === self.description_line; }); + if (to_add) { + day.lines = _.without(day.lines, to_add); + day.lines.unshift(to_add); + } else { + day.lines.unshift(_.extend(_.clone(account_defaults), { + name: self.description_line, + unit_amount: 0, + date: time.date_to_str(date), + account_id: account_id, + })); + } + return day; + }); + return {account: account_id, days: days, account_defaults: account_defaults}; + }).value(); + + // we need the name_get of the analytic accounts + return new Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"), + new data.CompoundContext()]).then(function(result) { + account_names = {}; + _.each(result, function(el) { + account_names[el[0]] = el[1]; + }); + accounts = _.sortBy(accounts, function(el) { + return account_names[el.account]; + }); + }); + }); + })).then(function(result) { + // we put all the gathered data in self, then we render + self.dates = dates; + self.accounts = accounts; + self.account_names = account_names; + self.default_get = default_get; + //real rendering + self.display_data(); + }); + }, + destroy_content: function() { + if (this.dfm) { + this.dfm.destroy(); + this.dfm = undefined; + } + }, + is_valid_value:function(value){ + var split_value = value.split(":"); + var valid_value = true; + if (split_value.length > 2) + return false; + _.detect(split_value,function(num){ + if(isNaN(num)){ + valid_value = false; + } + }); + return valid_value; + }, + display_data: function() { + var self = this; + self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self})); + _.each(self.accounts, function(account) { + _.each(_.range(account.days.length), function(day_count) { + if (!self.get('effective_readonly')) { + self.get_box(account, day_count).val(self.sum_box(account, day_count, true)).change(function() { + var num = $(this).val(); + if (self.is_valid_value(num)){ + num = (num === 0)?0:Number(self.parse_client(num)); + } + if (isNaN(num)) { + $(this).val(self.sum_box(account, day_count, true)); + } else { + account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count); + var product = (account.days[day_count].lines[0].product_id instanceof Array) ? account.days[day_count].lines[0].product_id[0] : account.days[day_count].lines[0].product_id; + var journal = (account.days[day_count].lines[0].journal_id instanceof Array) ? account.days[day_count].lines[0].journal_id[0] : account.days[day_count].lines[0].journal_id; + self.defs.push(new Model("hr.analytic.timesheet").call("on_change_unit_amount", [[], product, account.days[day_count].lines[0].unit_amount, false, false, journal]).then(function(res) { + account.days[day_count].lines[0]['amount'] = res.value.amount || 0; + self.display_totals(); + self.sync(); + })); + if(!isNaN($(this).val())){ + $(this).val(self.sum_box(account, day_count, true)); + } + } + }); + } else { + self.get_box(account, day_count).html(self.sum_box(account, day_count, true)); } }); - return valid_value; - }, - display_data: function() { - var self = this; - self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self})); - _.each(self.accounts, function(account) { - _.each(_.range(account.days.length), function(day_count) { - if (!self.get('effective_readonly')) { - self.get_box(account, day_count).val(self.sum_box(account, day_count, true)).change(function() { - var num = $(this).val(); - if (self.is_valid_value(num)){ - num = (num == 0)?0:Number(self.parse_client(num)); - } - if (isNaN(num)) { - $(this).val(self.sum_box(account, day_count, true)); - } else { - account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count); - var product = (account.days[day_count].lines[0].product_id instanceof Array) ? account.days[day_count].lines[0].product_id[0] : account.days[day_count].lines[0].product_id - var journal = (account.days[day_count].lines[0].journal_id instanceof Array) ? account.days[day_count].lines[0].journal_id[0] : account.days[day_count].lines[0].journal_id - self.defs.push(new instance.web.Model("hr.analytic.timesheet").call("on_change_unit_amount", [[], product, account.days[day_count].lines[0].unit_amount, false, false, journal]).then(function(res) { - account.days[day_count].lines[0]['amount'] = res.value.amount || 0; - self.display_totals(); - self.sync(); - })); - if(!isNaN($(this).val())){ - $(this).val(self.sum_box(account, day_count, true)); - } + }); + self.display_totals(); + self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this)); + }, + init_add_account: function() { + var self = this; + if (self.dfm) + return; + self.$(".oe_timesheet_weekly_add_row").show(); + self.dfm = new form_common.DefaultFieldManager(self); + self.dfm.extend_field_desc({ + account: { + relation: "account.analytic.account", + }, + }); + var FieldMany2One = core.form_widget_registry.get('many2one'); + self.account_m2o = new FieldMany2One(self.dfm, { + attrs: { + name: "account", + type: "many2one", + domain: [ + ['type','in',['normal', 'contract']], + ['state', '<>', 'close'], + ['invoice_on_timesheets','=',1], + ['id', 'not in', _.pluck(self.accounts, "account")], + ], + context: { + default_invoice_on_timesheets: 1, + default_type: "contract", + }, + modifiers: '{"required": true}', + }, + }); + self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td")); + self.$(".oe_timesheet_weekly_add_row button").click(function() { + var id = self.account_m2o.get_value(); + if (id === false) { + self.dfm.set({display_invalid_fields: true}); + return; + } + var ops = self.generate_o2m_value(); + new Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], [id], + new data.CompoundContext({'user_id': self.get('user_id')})]).then(function(res) { + res = res[id]; + var def = _.extend({}, self.default_get, res.value, { + name: self.description_line, + unit_amount: 0, + date: time.date_to_str(self.dates[0]), + account_id: id, + }); + ops.push(def); + self.set({"sheets": ops}); + }); + }); + }, + get_box: function(account, day_count) { + return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]'); + }, + get_total: function(account) { + return this.$('[data-account-total="' + account.account + '"]'); + }, + get_day_total: function(day_count) { + return this.$('[data-day-total="' + day_count + '"]'); + }, + get_super_total: function() { + return this.$('.oe_timesheet_weekly_supertotal'); + }, + sum_box: function(account, day_count, show_value_in_hour) { + var line_total = 0; + _.each(account.days[day_count].lines, function(line) { + line_total += line.unit_amount; + }); + return (show_value_in_hour && line_total !== 0)?this.format_client(line_total):line_total; + }, + display_totals: function() { + var self = this; + var day_tots = _.map(_.range(self.dates.length), function() { return 0; }); + var super_tot = 0; + _.each(self.accounts, function(account) { + var acc_tot = 0; + _.each(_.range(self.dates.length), function(day_count) { + var sum = self.sum_box(account, day_count); + acc_tot += sum; + day_tots[day_count] += sum; + super_tot += sum; + }); + self.get_total(account).html(self.format_client(acc_tot)); + }); + _.each(_.range(self.dates.length), function(day_count) { + self.get_day_total(day_count).html(self.format_client(day_tots[day_count])); + }); + self.get_super_total().html(self.format_client(super_tot)); + }, + sync: function() { + var self = this; + self.setting = true; + self.set({sheets: this.generate_o2m_value()}); + self.setting = false; + }, + //converts hour value to float + parse_client: function(value) { + return formats.parse_value(value, { type:"float_time" }); + }, + //converts float value to hour + format_client:function(value){ + return formats.format_value(value, { type:"float_time" }); + }, + generate_o2m_value: function() { + var self = this; + var ops = []; + var ignored_fields = self.ignore_fields(); + _.each(self.accounts, function(account) { + _.each(account.days, function(day) { + _.each(day.lines, function(line) { + if (line.unit_amount !== 0) { + var tmp = _.clone(line); + tmp.id = undefined; + _.each(line, function(v, k) { + if (v instanceof Array) { + tmp[k] = v[0]; } }); - } else { - self.get_box(account, day_count).html(self.sum_box(account, day_count, true)); + // we remove line_id as the reference to the _inherits field will no longer exists + tmp = _.omit(tmp, ignored_fields); + ops.push(tmp); } }); }); - self.display_totals(); - self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this)); - }, - init_add_account: function() { - var self = this; - if (self.dfm) - return; - self.$(".oe_timesheet_weekly_add_row").show(); - self.dfm = new instance.web.form.DefaultFieldManager(self); - self.dfm.extend_field_desc({ - account: { - relation: "account.analytic.account", - }, - }); - self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, { - attrs: { - name: "account", - type: "many2one", - domain: [ - ['type','in',['normal', 'contract']], - ['state', '<>', 'close'], - ['invoice_on_timesheets','=',1], - ['id', 'not in', _.pluck(self.accounts, "account")], - ], - context: { - default_invoice_on_timesheets: 1, - default_type: "contract", - }, - modifiers: '{"required": true}', - }, - }); - self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td")); - self.$(".oe_timesheet_weekly_add_row button").click(function() { - var id = self.account_m2o.get_value(); - if (id === false) { - self.dfm.set({display_invalid_fields: true}); - return; - } - var ops = self.generate_o2m_value(); - new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], [id], - new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(res) { - res = res[id]; - var def = _.extend({}, self.default_get, res.value, { - name: self.description_line, - unit_amount: 0, - date: instance.web.date_to_str(self.dates[0]), - account_id: id, - }); - ops.push(def); - self.set({"sheets": ops}); - }); - }); - }, - get_box: function(account, day_count) { - return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]'); - }, - get_total: function(account) { - return this.$('[data-account-total="' + account.account + '"]'); - }, - get_day_total: function(day_count) { - return this.$('[data-day-total="' + day_count + '"]'); - }, - get_super_total: function() { - return this.$('.oe_timesheet_weekly_supertotal'); - }, - sum_box: function(account, day_count, show_value_in_hour) { - var line_total = 0; - _.each(account.days[day_count].lines, function(line) { - line_total += line.unit_amount; - }); - return (show_value_in_hour && line_total != 0)?this.format_client(line_total):line_total; - }, - display_totals: function() { - var self = this; - var day_tots = _.map(_.range(self.dates.length), function() { return 0 }); - var super_tot = 0; - _.each(self.accounts, function(account) { - var acc_tot = 0; - _.each(_.range(self.dates.length), function(day_count) { - var sum = self.sum_box(account, day_count); - acc_tot += sum; - day_tots[day_count] += sum; - super_tot += sum; - }); - self.get_total(account).html(self.format_client(acc_tot)); - }); - _.each(_.range(self.dates.length), function(day_count) { - self.get_day_total(day_count).html(self.format_client(day_tots[day_count])); - }); - self.get_super_total().html(self.format_client(super_tot)); - }, - sync: function() { - var self = this; - self.setting = true; - self.set({sheets: this.generate_o2m_value()}); - self.setting = false; - }, - //converts hour value to float - parse_client: function(value) { - return instance.web.parse_value(value, { type:"float_time" }); - }, - //converts float value to hour - format_client:function(value){ - return instance.web.format_value(value, { type:"float_time" }); - }, - generate_o2m_value: function() { - var self = this; - var ops = []; - var ignored_fields = self.ignore_fields(); - _.each(self.accounts, function(account) { - _.each(account.days, function(day) { - _.each(day.lines, function(line) { - if (line.unit_amount !== 0) { - var tmp = _.clone(line); - tmp.id = undefined; - _.each(line, function(v, k) { - if (v instanceof Array) { - tmp[k] = v[0]; - } - }); - // we remove line_id as the reference to the _inherits field will no longer exists - tmp = _.omit(tmp, ignored_fields); - ops.push(tmp); - } - }); - }); - }); - return ops; - }, - }); + }); + return ops; + }, +}); - instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet'); +core.form_custom_registry.add('weekly_timesheet', WeeklyTimesheet); -}; +});