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