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