Auftrags-Controller: Einfüge-Position eines neuen Artiklens angeben können
[kivitendo-erp.git] / js / kivi.Order.js
1 namespace('kivi.Order', function(ns) {
2   ns.check_cv = function() {
3     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation') {
4       if ($('#order_customer_id').val() === '') {
5         alert(kivi.t8('Please select a customer.'));
6         return false;
7       }
8     } else  {
9       if ($('#order_vendor_id').val() === '') {
10         alert(kivi.t8('Please select a vendor.'));
11         return false;
12       }
13     }
14     return true;
15   };
16
17   ns.check_duplicate_parts = function(question) {
18     var id_arr = $('[name="order.orderitems[].parts_id"]').map(function() { return this.value; }).get();
19
20     var i, obj = {}, pos = [];
21
22     for (i = 0; i < id_arr.length; i++) {
23       var id = id_arr[i];
24       if (obj.hasOwnProperty(id)) {
25         pos.push(i + 1);
26       }
27       obj[id] = 0;
28     }
29
30     if (pos.length > 0) {
31       question = question || kivi.t8("Do you really want to save?");
32       return confirm(kivi.t8("There are duplicate parts at positions") + "\n"
33                      + pos.join(', ') + "\n"
34                      + question);
35     }
36     return true;
37   };
38
39   ns.check_valid_reqdate = function() {
40     if ($('#order_reqdate_as_date').val() === '') {
41       alert(kivi.t8('Please select a delivery date.'));
42       return false;
43     } else {
44       return true;
45     }
46   };
47
48   ns.save = function(action, warn_on_duplicates, warn_on_reqdate) {
49     if (!ns.check_cv()) return;
50     if (warn_on_duplicates && !ns.check_duplicate_parts()) return;
51     if (warn_on_reqdate    && !ns.check_valid_reqdate())   return;
52
53     var data = $('#order_form').serializeArray();
54     data.push({ name: 'order.language_id', value: $('#language_id').val() }); // language from print options
55     data.push({ name: 'action', value: 'Order/' + action });
56
57     $.post("controller.pl", data, kivi.eval_json_result);
58   };
59
60   ns.delete_order = function() {
61     var data = $('#order_form').serializeArray();
62     data.push({ name: 'action', value: 'Order/delete' });
63
64     $.post("controller.pl", data, kivi.eval_json_result);
65   };
66
67   ns.show_print_options = function(warn_on_duplicates) {
68     if (!ns.check_cv()) return;
69     if (warn_on_duplicates && !ns.check_duplicate_parts(kivi.t8("Do you really want to print?"))) return;
70
71     kivi.popup_dialog({
72       id: 'print_options',
73       dialog: {
74         title: kivi.t8('Print options'),
75         width:  800,
76         height: 300
77       }
78     });
79   };
80
81   ns.print = function() {
82     $('#print_options').dialog('close');
83
84     var data = $('#order_form').serializeArray();
85     data = data.concat($('#print_options_form').serializeArray());
86     data.push({ name: 'order.language_id', value: $('#language_id').val() }); // language from print options
87     data.push({ name: 'action', value: 'Order/print' });
88
89     $.post("controller.pl", data, kivi.eval_json_result);
90   };
91
92   ns.email = function(warn_on_duplicates) {
93     if (warn_on_duplicates && !ns.check_duplicate_parts(kivi.t8("Do you really want to send by mail?"))) return;
94     if (!ns.check_cv()) return;
95
96     var data = $('#order_form').serializeArray();
97     data.push({ name: 'action', value: 'Order/show_email_dialog' });
98
99     $.post("controller.pl", data, kivi.eval_json_result);
100   };
101
102   var email_dialog;
103
104   ns.setup_send_email_dialog = function() {
105     kivi.SalesPurchase.show_all_print_options_elements();
106     kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false);
107
108     $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
109
110     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
111     $('#email_form_' + to_focus).focus();
112   };
113
114   ns.finish_send_email_dialog = function() {
115     kivi.SalesPurchase.show_all_print_options_elements();
116
117     $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
118     return true;
119   };
120
121   ns.show_email_dialog = function(html) {
122     var id            = 'send_email_dialog';
123     var dialog_params = {
124       id:     id,
125       width:  800,
126       height: 600,
127       title:  kivi.t8('Send email'),
128       modal:  true,
129       beforeClose: kivi.Order.finish_send_email_dialog,
130       close: function(event, ui) {
131         email_dialog.remove();
132       }
133     };
134
135     $('#' + id).remove();
136
137     email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
138     email_dialog.html(html);
139     email_dialog.dialog(dialog_params);
140
141     kivi.Order.setup_send_email_dialog();
142
143     $('.cancel').click(ns.close_email_dialog);
144
145     return true;
146   };
147
148   ns.send_email = function() {
149     var data = $('#order_form').serializeArray();
150     data = data.concat($('[name^="email_form."]').serializeArray());
151     data = data.concat($('[name^="print_options."]').serializeArray());
152     data.push({ name: 'order.language_id', value: $('#language_id').val() }); // language from print options
153     data.push({ name: 'action', value: 'Order/send_email' });
154     $.post("controller.pl", data, kivi.eval_json_result);
155   };
156
157   ns.close_email_dialog = function() {
158     email_dialog.dialog("close");
159   };
160
161   ns.set_number_in_title = function(elt) {
162     $('#nr_in_title').html($(elt).val());
163   };
164
165   ns.reload_cv_dependant_selections = function() {
166     var data = $('#order_form').serializeArray();
167     data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
168
169     $.post("controller.pl", data, kivi.eval_json_result);
170   };
171
172   ns.reformat_number = function(event) {
173     $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
174   };
175
176   ns.recalc_amounts_and_taxes = function() {
177     var data = $('#order_form').serializeArray();
178     data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
179
180     $.post("controller.pl", data, kivi.eval_json_result);
181   };
182
183   ns.unit_change = function(event) {
184     var row           = $(event.target).parents("tbody").first();
185     var item_id_dom   = $(row).find('[name="orderitem_ids[+]"]');
186     var sellprice_dom = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
187     var select_elt    = $(row).find('[name="order.orderitems[].unit"]');
188
189     var oldval = $(select_elt).data('oldval');
190     $(select_elt).data('oldval', $(select_elt).val());
191
192     var data = $('#order_form').serializeArray();
193     data.push({ name: 'action',           value: 'Order/unit_changed'     },
194               { name: 'item_id',          value: item_id_dom.val()        },
195               { name: 'old_unit',         value: oldval                   },
196               { name: 'sellprice_dom_id', value: sellprice_dom.attr('id') });
197
198     $.post("controller.pl", data, kivi.eval_json_result);
199   };
200
201   ns.update_sellprice = function(item_id, price_str) {
202     var row       = $('#item_' + item_id).parents("tbody").first();
203     var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
204     var html_elt  = $(row).find('[name="sellprice_text"]');
205     price_elt.val(price_str);
206     html_elt.html(price_str);
207   };
208
209   ns.load_second_row = function(row) {
210     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
211     var div_elt     = $(row).find('[name="second_row"]');
212
213     if ($(div_elt).data('loaded') == 1) {
214       return;
215     }
216     var data = $('#order_form').serializeArray();
217     data.push({ name: 'action',     value: 'Order/load_second_rows' },
218               { name: 'item_ids[]', value: item_id_dom.val()        });
219
220     $.post("controller.pl", data, kivi.eval_json_result);
221   };
222
223   ns.load_all_second_rows = function() {
224     var rows = $('.row_entry').filter(function(idx, elt) {
225       return $(elt).find('[name="second_row"]').data('loaded') != 1;
226     });
227
228     var item_ids = $.map(rows, function(elt) {
229       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
230       return { name: 'item_ids[]', value: item_id };
231     });
232
233     if (item_ids.length == 0) {
234       return;
235     }
236
237     var data = $('#order_form').serializeArray();
238     data.push({ name: 'action', value: 'Order/load_second_rows' });
239     data = data.concat(item_ids);
240
241     $.post("controller.pl", data, kivi.eval_json_result);
242   };
243
244   ns.hide_second_row = function(row) {
245     $(row).children().not(':first').hide();
246     $(row).data('expanded', 0);
247     var elt = $(row).find('.expand');
248     elt.attr('src', "image/expand.svg");
249     elt.attr('alt', kivi.t8('Show details'));
250     elt.attr('title', kivi.t8('Show details'));
251   };
252
253   ns.show_second_row = function(row) {
254     $(row).children().not(':first').show();
255     $(row).data('expanded', 1);
256     var elt = $(row).find('.expand');
257     elt.attr('src', "image/collapse.svg");
258     elt.attr('alt', kivi.t8('Hide details'));
259     elt.attr('title', kivi.t8('Hide details'));
260   };
261
262   ns.toggle_second_row = function(row) {
263     if ($(row).data('expanded') == 1) {
264       ns.hide_second_row(row);
265     } else {
266       ns.show_second_row(row);
267     }
268   };
269
270   ns.init_row_handlers = function() {
271     kivi.run_once_for('.recalc', 'on_change_recalc', function(elt) {
272       $(elt).change(ns.recalc_amounts_and_taxes);
273     });
274
275     kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
276       $(elt).change(ns.reformat_number);
277     });
278
279     kivi.run_once_for('.unitselect', 'on_change_unit_with_oldval', function(elt) {
280       $(elt).data('oldval', $(elt).val());
281       $(elt).change(ns.unit_change);
282     });
283
284     kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
285       $(elt).keydown(function(event) {
286         var row;
287         if (event.keyCode == 40 && event.shiftKey === true) {
288           // shift arrow down
289           event.preventDefault();
290           row = $(event.target).parents(".row_entry").first();
291           ns.load_second_row(row);
292           ns.show_second_row(row);
293           return false;
294         }
295         if (event.keyCode == 38 && event.shiftKey === true) {
296           // shift arrow up
297           event.preventDefault();
298           row = $(event.target).parents(".row_entry").first();
299           ns.hide_second_row(row);
300           return false;
301         }
302       });
303     });
304
305     kivi.run_once_for('.expand', 'expand_second_row', function(elt) {
306       $(elt).click(function(event) {
307         event.preventDefault();
308         var row = $(event.target).parents(".row_entry").first();
309         ns.load_second_row(row);
310         ns.toggle_second_row(row);
311         return false;
312       })
313     });
314
315   };
316
317   ns.redisplay_line_values = function(is_sales, data) {
318     $('.row_entry').each(function(idx, elt) {
319       $(elt).find('[name="linetotal"]').html(data[idx][0]);
320       if (is_sales && $(elt).find('[name="second_row"]').data('loaded') == 1) {
321         var mt = data[idx][1];
322         var mp = data[idx][2];
323         var h  = '<span';
324         if (mt[0] === '-') h += ' class="plus0"';
325         h += '>' + mt + '&nbsp;&nbsp;' + mp + '%';
326         h += '</span>';
327         $(elt).find('[name="linemargin"]').html(h);
328       }
329     });
330   };
331
332   ns.redisplay_cvpartnumbers = function(data) {
333     $('.row_entry').each(function(idx, elt) {
334       $(elt).find('[name="cvpartnumber"]').html(data[idx][0]);
335     });
336   };
337
338   ns.renumber_positions = function() {
339     $('.row_entry [name="position"]').each(function(idx, elt) {
340       $(elt).html(idx+1);
341     });
342     $('.row_entry').each(function(idx, elt) {
343       $(elt).data("position", idx+1);
344     });
345   };
346
347   ns.reorder_items = function(order_by) {
348     var dir = $('#' + order_by + '_header_id a img').attr("data-sort-dir");
349     $('#row_table_id thead a img').remove();
350
351     var src;
352     if (dir == "1") {
353       dir = "0";
354       src = "image/up.png";
355     } else {
356       dir = "1";
357       src = "image/down.png";
358     }
359
360     $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
361
362     var data = $('#order_form').serializeArray();
363     data.push({ name: 'action',   value: 'Order/reorder_items' },
364               { name: 'order_by', value: order_by              },
365               { name: 'sort_dir', value: dir                   });
366
367     $.post("controller.pl", data, kivi.eval_json_result);
368   };
369
370   ns.redisplay_items = function(data) {
371     var old_rows = $('.row_entry').detach();
372     var new_rows = [];
373     $(data).each(function(idx, elt) {
374       new_rows.push(old_rows[elt.old_pos - 1]);
375     });
376     $(new_rows).appendTo($('#row_table_id'));
377     ns.renumber_positions();
378   };
379
380   ns.get_insert_before_item_id = function(wanted_pos) {
381     if (wanted_pos === '') return;
382
383     var insert_before_item_id;
384     // selection by data does not seem to work if data is changed at runtime
385     // var elt = $('.row_entry [data-position="' + wanted_pos + '"]');
386     $('.row_entry').each(function(idx, elt) {
387       if ($(elt).data("position") == wanted_pos) {
388         insert_before_item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
389         return false;
390       }
391     });
392
393     return insert_before_item_id;
394   };
395
396   ns.add_item = function() {
397     if ($('#add_item_parts_id').val() === '') return;
398     if (!ns.check_cv()) return;
399
400     $('#row_table_id thead a img').remove();
401
402     var insert_before_item_id = ns.get_insert_before_item_id($('#add_item_position').val());
403
404     var data = $('#order_form').serializeArray();
405     data.push({ name: 'action', value: 'Order/add_item' },
406               { name: 'insert_before_item_id', value: insert_before_item_id });
407
408     $.post("controller.pl", data, kivi.eval_json_result);
409   };
410
411   ns.setup_multi_items_dialog = function() {
412     $('#multi_items_filter_table input, #multi_items_filter_table select').keydown(function(event) {
413       if (event.keyCode == 13) {
414         event.preventDefault();
415         ns.multi_items_dialog_update_result();
416         return false;
417       }
418     });
419
420     $('#multi_items_filter_all_substr_multi_ilike').focus();
421   };
422
423   ns.show_multi_items_dialog = function() {
424     if (!ns.check_cv()) return;
425
426     $('#row_table_id thead a img').remove();
427
428     kivi.popup_dialog({
429       url:    'controller.pl?action=Order/show_multi_items_dialog',
430       data:   { type: $('#type').val() },
431       id:     'jq_multi_items_dialog',
432       load:   kivi.Order.setup_multi_items_dialog,
433       dialog: {
434         title:  kivi.t8('Add multiple items'),
435         width:  800,
436         height: 500
437       }
438     });
439     return true;
440   };
441
442   ns.close_multi_items_dialog = function() {
443     $('#jq_multi_items_dialog').dialog('close');
444   };
445
446   ns.multi_items_dialog_update_result = function() {
447     var data = $('#multi_items_form').serializeArray();
448     data.push({ name: 'type', value: $('#type').val() });
449     $.ajax({
450       url:     'controller.pl?action=Order/multi_items_update_result',
451       data:    data,
452       method:  'post',
453       success: function(data) {
454         $('#multi_items_result').html(data);
455         ns.multi_items_dialog_enable_continue();
456         ns.multi_items_result_setup_events();
457       }
458     });
459   };
460
461   ns.multi_items_dialog_disable_continue = function() {
462     // disable keydown-event and continue button to prevent
463     // impatient users to add parts multiple times
464     $('#multi_items_result input, #multi_items_position').off("keydown");
465     $('#multi_items_dialog_continue_button').prop('disabled', true);
466   };
467
468   ns.multi_items_dialog_enable_continue = function()  {
469     $('#multi_items_result input, #multi_items_position').keydown(function(event) {
470       if(event.keyCode == 13) {
471         event.preventDefault();
472         ns.add_multi_items();
473         return false;
474       }
475     });
476     $('#multi_items_dialog_continue_button').prop('disabled', false);
477   };
478
479   ns.multi_items_result_setup_events = function() {
480     $('#multi_items_all_qty').change(ns.reformat_number);
481     $('#multi_items_all_qty').change(function(event) {
482       $('.multi_items_qty').val($(event.target).val());
483     });
484     $('.multi_items_qty').change(ns.reformat_number);
485   }
486
487   ns.add_multi_items = function() {
488     // rows at all
489     var n_rows = $('.multi_items_qty').length;
490     if (n_rows == 0) return;
491
492     // filled rows
493     n_rows = $('.multi_items_qty').filter(function() {
494       return $(this).val().length > 0;
495     }).length;
496     if (n_rows == 0) return;
497
498     ns.multi_items_dialog_disable_continue();
499
500     var insert_before_item_id = ns.get_insert_before_item_id($('#multi_items_position').val());
501
502     var data = $('#order_form').serializeArray();
503     data = data.concat($('#multi_items_form').serializeArray());
504     data.push({ name: 'action', value: 'Order/add_multi_items' },
505               { name: 'insert_before_item_id', value: insert_before_item_id });
506     $.post("controller.pl", data, kivi.eval_json_result);
507   };
508
509   ns.set_input_to_one = function(clicked) {
510     if ($(clicked).val() == '') {
511       $(clicked).val(kivi.format_amount(1.00, -2));
512     }
513     $(clicked).select();
514   };
515
516   ns.delete_order_item_row = function(clicked) {
517     var row = $(clicked).parents("tbody").first();
518     $(row).remove();
519
520     ns.renumber_positions();
521     ns.recalc_amounts_and_taxes();
522   };
523
524   ns.row_table_scroll_down = function() {
525     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
526   };
527
528   ns.show_longdescription_dialog = function(clicked) {
529     var row                 = $(clicked).parents("tbody").first();
530     var position            = $(row).find('[name="position"]').html();
531     var partnumber          = $(row).find('[name="partnumber"]').html();
532     var description_elt     = $(row).find('[name="order.orderitems[].description"]');
533     var description         = description_elt.val();
534     var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
535     var longdescription;
536
537     if (!longdescription_elt.length) {
538       var data = [
539         { name: 'action',   value: 'Order/get_item_longdescription'                          },
540         { name: 'type',     value: $('#type').val()                                          },
541         { name: 'item_id',  value: $(row).find('[name="order.orderitems[+].id"]').val()      },
542         { name: 'parts_id', value: $(row).find('[name="order.orderitems[].parts_id"]').val() }
543       ];
544
545       $.ajax({
546         url:      'controller.pl',
547         data:     data,
548         method:   "GET",
549         async:    false,
550         dataType: 'text',
551         success:  function(val) {
552           longdescription = val;
553         }
554       });
555     } else {
556       longdescription = longdescription_elt.val();
557     }
558
559     var params = {
560       runningnumber:           position,
561       partnumber:              partnumber,
562       description:             description,
563       default_longdescription: longdescription,
564       set_function:            function(val) {
565         longdescription_elt.remove();
566         $('<input type="hidden" name="order.orderitems[].longdescription">').insertAfter(description_elt).val(val);
567       }
568     };
569
570     kivi.SalesPurchase.edit_longdescription_with_params(params);
571   };
572
573   ns.price_chooser_item_row = function(clicked) {
574     if (!ns.check_cv()) return;
575     var row         = $(clicked).parents("tbody").first();
576     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
577
578     var data = $('#order_form').serializeArray();
579     data.push({ name: 'action',  value: 'Order/price_popup' },
580               { name: 'item_id', value: item_id_dom.val()   });
581
582     $.post("controller.pl", data, kivi.eval_json_result);
583   };
584
585   ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
586     var row        = $('#item_' + item_id).parents("tbody").first();
587     var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
588     var button_elt = $(row).find('[name="price_chooser_button"]');
589
590     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
591     source_elt.val(source);
592
593     var editable_div_elt     = $(row).find('[name="editable_price"]');
594     var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
595     if (price_editable == 1 && source === '') {
596       // editable
597       $(editable_div_elt).show();
598       $(not_editable_div_elt).hide();
599       $(editable_div_elt).find(':input').prop("disabled", false);
600       $(not_editable_div_elt).find(':input').prop("disabled", true);
601     } else {
602       // not editable
603       $(editable_div_elt).hide();
604       $(not_editable_div_elt).show();
605       $(editable_div_elt).find(':input').prop("disabled", true);
606       $(not_editable_div_elt).find(':input').prop("disabled", false);
607     }
608
609     if (price_str) {
610       var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
611       var html_elt  = $(row).find('[name="sellprice_text"]');
612       price_elt.val(price_str);
613       html_elt.html(price_str);
614       ns.recalc_amounts_and_taxes();
615     }
616
617     kivi.io.close_dialog();
618   };
619
620   ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
621     var row        = $('#item_' + item_id).parents("tbody").first();
622     var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
623     var button_elt = $(row).find('[name="price_chooser_button"]');
624
625     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
626     source_elt.val(source);
627
628     var editable_div_elt     = $(row).find('[name="editable_discount"]');
629     var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
630     if (price_editable == 1 && source === '') {
631       // editable
632       $(editable_div_elt).show();
633       $(not_editable_div_elt).hide();
634       $(editable_div_elt).find(':input').prop("disabled", false);
635       $(not_editable_div_elt).find(':input').prop("disabled", true);
636     } else {
637       // not editable
638       $(editable_div_elt).hide();
639       $(not_editable_div_elt).show();
640       $(editable_div_elt).find(':input').prop("disabled", true);
641       $(not_editable_div_elt).find(':input').prop("disabled", false);
642     }
643
644     if (discount_str) {
645       var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
646       var html_elt     = $(row).find('[name="discount_text"]');
647       discount_elt.val(discount_str);
648       html_elt.html(discount_str);
649       ns.recalc_amounts_and_taxes();
650     }
651
652     kivi.io.close_dialog();
653   };
654
655   ns.show_periodic_invoices_config_dialog = function() {
656     if ($('#type').val() !== 'sales_order') return;
657
658     kivi.popup_dialog({
659       url:    'controller.pl?action=Order/show_periodic_invoices_config_dialog',
660       data:   { type:              $('#type').val(),
661                 id:                $('#id').val(),
662                 config:            $('#order_periodic_invoices_config').val(),
663                 customer_id:       $('#order_customer_id').val(),
664                 transdate_as_date: $('#order_transdate_as_date').val(),
665                 language_id:       $('#language_id').val()
666               },
667       id:     'jq_periodic_invoices_config_dialog',
668       load:   kivi.reinit_widgets,
669       dialog: {
670         title:  kivi.t8('Edit the configuration for periodic invoices'),
671         width:  800,
672         height: 650
673       }
674     });
675     return true;
676   };
677
678   ns.close_periodic_invoices_config_dialog = function() {
679     $('#jq_periodic_invoices_config_dialog').dialog('close');
680   };
681
682   ns.assign_periodic_invoices_config = function() {
683     var data = $('[name="Form"]').serializeArray();
684     data.push({ name: 'type',   value: $('#type').val() },
685               { name: 'action', value: 'Order/assign_periodic_invoices_config' });
686     $.post("controller.pl", data, kivi.eval_json_result);
687   };
688
689   ns.check_save_active_periodic_invoices = function() {
690     var type = $('#type').val();
691     if (type !== 'sales_order') return true;
692
693     var active = false;
694     $.ajax({
695       url:      'controller.pl',
696       data:     { action: 'Order/get_has_active_periodic_invoices',
697                   type  : type,
698                   id    : $('#id').val(),
699                   config: $('#order_periodic_invoices_config').val(),
700                 },
701       method:   "GET",
702       async:    false,
703       dataType: 'text',
704       success:  function(val) {
705         active = val;
706       }
707     });
708
709     if (active == 1) {
710       return confirm(kivi.t8('This sales order has an active configuration for periodic invoices. If you save then all subsequently created invoices will contain those changes as well, but not those that have already been created. Do you want to continue?'));
711     }
712
713     return true;
714   };
715
716   ns.show_vc_details_dialog = function() {
717     if (!ns.check_cv()) return;
718     var vc;
719     var vc_id;
720     var title;
721     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
722       vc    = 'customer';
723       vc_id = $('#order_customer_id').val();
724       title = kivi.t8('Customer details');
725     } else {
726       vc    = 'vendor';
727       vc_id = $('#order_vendor_id').val();
728       title = kivi.t8('Vendor details');
729     }
730
731     kivi.popup_dialog({
732       url:    'controller.pl',
733       data:   { action: 'Order/show_customer_vendor_details_dialog',
734                 type  : $('#type').val(),
735                 vc    : vc,
736                 vc_id : vc_id
737               },
738       id:     'jq_customer_vendor_details_dialog',
739       dialog: {
740         title:  title,
741         width:  800,
742         height: 650
743       }
744     });
745     return true;
746   };
747
748   ns.update_row_from_master_data = function(clicked) {
749     var row = $(clicked).parents("tbody").first();
750     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
751
752     var data = $('#order_form').serializeArray();
753     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
754     data.push({ name: 'item_ids[]', value: item_id_dom.val() });
755
756     $.post("controller.pl", data, kivi.eval_json_result);
757   };
758
759   ns.update_all_rows_from_master_data = function() {
760     var item_ids = $.map($('.row_entry'), function(elt) {
761       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
762       return { name: 'item_ids[]', value: item_id };
763     });
764
765     if (item_ids.length == 0) {
766       return;
767     }
768
769     var data = $('#order_form').serializeArray();
770     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
771     data = data.concat(item_ids);
772
773     $.post("controller.pl", data, kivi.eval_json_result);
774   };
775
776   ns.show_calculate_qty_dialog = function(clicked) {
777     var row        = $(clicked).parents("tbody").first();
778     var input_id   = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
779     var formula_id = $(row).find('[name="formula[+]"]').attr('id');
780
781     calculate_qty_selection_dialog("", input_id, "", formula_id);
782     return true;
783   };
784
785 });
786
787 $(function() {
788   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
789     $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
790   } else {
791     $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
792   }
793
794   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
795     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
796   } else {
797     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
798   }
799   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
800   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
801
802   $('.add_item_input').keydown(function(event) {
803     if (event.keyCode == 13) {
804       event.preventDefault();
805       kivi.Order.add_item();
806       return false;
807     }
808   });
809
810   kivi.Order.init_row_handlers();
811
812   $('#row_table_id').on('sortstop', function(event, ui) {
813     $('#row_table_id thead a img').remove();
814     kivi.Order.renumber_positions();
815   });
816
817   $('#expand_all').on('click', function(event) {
818     event.preventDefault();
819     if ($('#expand_all').data('expanded') == 1) {
820       $('#expand_all').data('expanded', 0);
821       $('#expand_all').attr('src', 'image/expand.svg');
822       $('#expand_all').attr('alt', kivi.t8('Show all details'));
823       $('#expand_all').attr('title', kivi.t8('Show all details'));
824       $('.row_entry').each(function(idx, elt) {
825         kivi.Order.hide_second_row(elt);
826       });
827     } else {
828       $('#expand_all').data('expanded', 1);
829       $('#expand_all').attr('src', "image/collapse.svg");
830       $('#expand_all').attr('alt', kivi.t8('Hide all details'));
831       $('#expand_all').attr('title', kivi.t8('Hide all details'));
832       kivi.Order.load_all_second_rows();
833       $('.row_entry').each(function(idx, elt) {
834         kivi.Order.show_second_row(elt);
835       });
836     }
837     return false;
838   });
839
840 });