2 openerp.hr_timesheet_sheet = function(instance) {
3 var QWeb = instance.web.qweb;
4 var _t = instance.web._t;
6 instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, {
8 "click .oe_timesheet_weekly_account a": "go_to",
11 this._super.apply(this, arguments);
18 this.updating = false;
20 this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets);
21 this.field_manager.on("field_changed:date_from", this, function() {
22 this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))});
24 this.field_manager.on("field_changed:date_to", this, function() {
25 this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))});
27 this.field_manager.on("field_changed:user_id", this, function() {
28 this.set({"user_id": this.field_manager.get_field_value("user_id")});
30 this.on("change:sheets", this, this.update_sheets);
31 this.res_o2m_drop = new instance.web.DropMisordered();
32 this.render_drop = new instance.web.DropMisordered();
33 this.description_line = _t("/");
34 // Original save function is overwritten in order to wait all running deferreds to be done before actually applying the save.
35 this.view.original_save = _.bind(this.view.save, this.view);
36 this.view.save = function(prepend_on_create){
37 self.prepend_on_create = prepend_on_create;
38 return $.when.apply($, self.defs).then(function(){
39 return self.view.original_save(self.prepend_on_create);
43 go_to: function(event) {
44 var id = JSON.parse($(event.target).data("id"));
46 type: 'ir.actions.act_window',
47 res_model: "account.analytic.account",
49 views: [[false, 'form']],
53 query_sheets: function() {
57 var commands = this.field_manager.get_field_value("timesheet_ids");
58 this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
59 new instance.web.CompoundContext()]))
60 .done(function(result) {
62 self.set({sheets: result});
63 self.querying = false;
66 update_sheets: function() {
71 self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
72 self.updating = false;
75 initialize_field: function() {
76 instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this);
78 self.on("change:sheets", self, self.initialize_content);
79 self.on("change:date_to", self, self.initialize_content);
80 self.on("change:date_from", self, self.initialize_content);
81 self.on("change:user_id", self, self.initialize_content);
83 initialize_content: function() {
87 // don't render anything until we have date_to and date_from
88 if (!self.get("date_to") || !self.get("date_from"))
90 this.destroy_content();
92 // it's important to use those vars to avoid race conditions
97 return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
98 ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
99 new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
100 default_get = result;
103 var start = self.get("date_from");
104 var end = self.get("date_to");
105 while (start <= end) {
107 start = start.clone().addDays(1);
110 accounts = _(self.get("sheets")).chain()
112 // much simpler to use only the id in all cases
113 if (typeof(el.account_id) === "object")
114 el.account_id = el.account_id[0];
117 .groupBy("account_id").value();
119 var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });
121 return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
122 new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
123 accounts = _(accounts).chain().map(function(lines, account_id) {
124 account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
126 account_id = account_id === "false" ? false : Number(account_id);
127 var index = _.groupBy(lines, "date");
128 var days = _.map(dates, function(date) {
129 var day = {day: date, lines: index[instance.web.date_to_str(date)] || []};
130 // add line where we will insert/remove hours
131 var to_add = _.find(day.lines, function(line) { return line.name === self.description_line });
133 day.lines = _.without(day.lines, to_add);
134 day.lines.unshift(to_add);
136 day.lines.unshift(_.extend(_.clone(account_defaults), {
137 name: self.description_line,
139 date: instance.web.date_to_str(date),
140 account_id: account_id,
145 return {account: account_id, days: days, account_defaults: account_defaults};
148 // we need the name_get of the analytic accounts
149 return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
150 new instance.web.CompoundContext()]).then(function(result) {
152 _.each(result, function(el) {
153 account_names[el[0]] = el[1];
155 accounts = _.sortBy(accounts, function(el) {
156 return account_names[el.account];
160 })).then(function(result) {
161 // we put all the gathered data in self, then we render
163 self.accounts = accounts;
164 self.account_names = account_names;
165 self.default_get = default_get;
170 destroy_content: function() {
173 this.dfm = undefined;
176 is_valid_value:function(value){
177 var split_value = value.split(":");
178 var valid_value = true;
179 if (split_value.length > 2)
181 _.detect(split_value,function(num){
188 display_data: function() {
190 self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self}));
191 _.each(self.accounts, function(account) {
192 _.each(_.range(account.days.length), function(day_count) {
193 if (!self.get('effective_readonly')) {
194 self.get_box(account, day_count).val(self.sum_box(account, day_count, true)).change(function() {
195 var num = $(this).val();
196 if (self.is_valid_value(num)){
197 num = (num == 0)?0:Number(self.parse_client(num));
200 $(this).val(self.sum_box(account, day_count, true));
202 account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
203 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
204 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
205 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) {
206 account.days[day_count].lines[0]['amount'] = res.value.amount || 0;
207 self.display_totals();
210 if(!isNaN($(this).val())){
211 $(this).val(self.sum_box(account, day_count, true));
216 self.get_box(account, day_count).html(self.sum_box(account, day_count, true));
220 self.display_totals();
221 self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this));
223 init_add_account: function() {
227 self.$(".oe_timesheet_weekly_add_row").show();
228 self.dfm = new instance.web.form.DefaultFieldManager(self);
229 self.dfm.extend_field_desc({
231 relation: "account.analytic.account",
234 self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, {
239 ['type','in',['normal', 'contract']],
240 ['state', '<>', 'close'],
241 ['use_timesheets','=',1],
242 ['id', 'not in', _.pluck(self.accounts, "account")],
245 default_use_timesheets: 1,
246 default_type: "contract",
248 modifiers: '{"required": true}',
251 self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td"));
252 self.$(".oe_timesheet_weekly_add_row button").click(function() {
253 var id = self.account_m2o.get_value();
255 self.dfm.set({display_invalid_fields: true});
258 var ops = self.generate_o2m_value();
259 new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
260 var def = _.extend({}, self.default_get, res.value, {
261 name: self.description_line,
263 date: instance.web.date_to_str(self.dates[0]),
267 self.set({"sheets": ops});
271 get_box: function(account, day_count) {
272 return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]');
274 get_total: function(account) {
275 return this.$('[data-account-total="' + account.account + '"]');
277 get_day_total: function(day_count) {
278 return this.$('[data-day-total="' + day_count + '"]');
280 get_super_total: function() {
281 return this.$('.oe_timesheet_weekly_supertotal');
283 sum_box: function(account, day_count, show_value_in_hour) {
285 _.each(account.days[day_count].lines, function(line) {
286 line_total += line.unit_amount;
288 return (show_value_in_hour && line_total != 0)?this.format_client(line_total):line_total;
290 display_totals: function() {
292 var day_tots = _.map(_.range(self.dates.length), function() { return 0 });
294 _.each(self.accounts, function(account) {
296 _.each(_.range(self.dates.length), function(day_count) {
297 var sum = self.sum_box(account, day_count);
299 day_tots[day_count] += sum;
302 self.get_total(account).html(self.format_client(acc_tot));
304 _.each(_.range(self.dates.length), function(day_count) {
305 self.get_day_total(day_count).html(self.format_client(day_tots[day_count]));
307 self.get_super_total().html(self.format_client(super_tot));
312 self.set({sheets: this.generate_o2m_value()});
313 self.setting = false;
315 //converts hour value to float
316 parse_client: function(value) {
317 return instance.web.parse_value(value, { type:"float_time" });
319 //converts float value to hour
320 format_client:function(value){
321 return instance.web.format_value(value, { type:"float_time" });
323 generate_o2m_value: function() {
327 _.each(self.accounts, function(account) {
328 var auth_keys = _.extend(_.clone(account.account_defaults), {
329 name: true, amount:true, unit_amount: true, date: true, account_id:true,
331 _.each(account.days, function(day) {
332 _.each(day.lines, function(line) {
333 if (line.unit_amount !== 0) {
334 var tmp = _.clone(line);
336 _.each(line, function(v, k) {
337 if (v instanceof Array) {
341 // we have to remove some keys, because analytic lines are shitty
342 _.each(_.keys(tmp), function(key) {
343 if (auth_keys[key] === undefined) {
344 tmp[key] = undefined;
356 instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet');