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