Auftrags-Controller: Artikel-Mehrfachauswahl: js-Code aus Template ausgelagert
[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.open_multi_items_dialog = function() {
462     var pp = $("#add_item_parts_id").data("part_picker");
463     pp.o.multiple=1;
464     pp.open_dialog();
465   };
466
467   ns.add_multi_items = function(data) {
468     var insert_before_item_id = ns.get_insert_before_item_id($('#multi_items_position').val());
469     data = data.concat($('#order_form').serializeArray());
470     data.push({ name: 'action', value: 'Order/add_multi_items' },
471               { name: 'insert_before_item_id', value: insert_before_item_id });
472     $.post("controller.pl", data, kivi.eval_json_result);
473   };
474
475   ns.delete_order_item_row = function(clicked) {
476     var row = $(clicked).parents("tbody").first();
477     $(row).remove();
478
479     ns.renumber_positions();
480     ns.recalc_amounts_and_taxes();
481   };
482
483   ns.row_table_scroll_down = function() {
484     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
485   };
486
487   ns.show_longdescription_dialog = function(clicked) {
488     var row                 = $(clicked).parents("tbody").first();
489     var position            = $(row).find('[name="position"]').html();
490     var partnumber          = $(row).find('[name="partnumber"]').html();
491     var description_elt     = $(row).find('[name="order.orderitems[].description"]');
492     var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
493
494     var params = {
495       runningnumber:           position,
496       partnumber:              partnumber,
497       description:             description_elt.val(),
498       default_longdescription: longdescription_elt.val(),
499       set_function:            function(val) {
500         longdescription_elt.val(val);
501       }
502     };
503
504     kivi.SalesPurchase.edit_longdescription_with_params(params);
505   };
506
507   ns.price_chooser_item_row = function(clicked) {
508     if (!ns.check_cv()) return;
509     var row         = $(clicked).parents("tbody").first();
510     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
511
512     var data = $('#order_form').serializeArray();
513     data.push({ name: 'action',  value: 'Order/price_popup' },
514               { name: 'item_id', value: item_id_dom.val()   });
515
516     $.post("controller.pl", data, kivi.eval_json_result);
517   };
518
519   ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
520     var row        = $('#item_' + item_id).parents("tbody").first();
521     var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
522     var button_elt = $(row).find('[name="price_chooser_button"]');
523
524     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
525     source_elt.val(source);
526
527     var editable_div_elt     = $(row).find('[name="editable_price"]');
528     var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
529     if (price_editable == 1 && source === '') {
530       // editable
531       $(editable_div_elt).show();
532       $(not_editable_div_elt).hide();
533       $(editable_div_elt).find(':input').prop("disabled", false);
534       $(not_editable_div_elt).find(':input').prop("disabled", true);
535     } else {
536       // not editable
537       $(editable_div_elt).hide();
538       $(not_editable_div_elt).show();
539       $(editable_div_elt).find(':input').prop("disabled", true);
540       $(not_editable_div_elt).find(':input').prop("disabled", false);
541     }
542
543     if (price_str) {
544       var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
545       var html_elt  = $(row).find('[name="sellprice_text"]');
546       price_elt.val(price_str);
547       html_elt.html(price_str);
548       ns.recalc_amounts_and_taxes();
549     }
550
551     kivi.io.close_dialog();
552   };
553
554   ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
555     var row        = $('#item_' + item_id).parents("tbody").first();
556     var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
557     var button_elt = $(row).find('[name="price_chooser_button"]');
558
559     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
560     source_elt.val(source);
561
562     var editable_div_elt     = $(row).find('[name="editable_discount"]');
563     var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
564     if (price_editable == 1 && source === '') {
565       // editable
566       $(editable_div_elt).show();
567       $(not_editable_div_elt).hide();
568       $(editable_div_elt).find(':input').prop("disabled", false);
569       $(not_editable_div_elt).find(':input').prop("disabled", true);
570     } else {
571       // not editable
572       $(editable_div_elt).hide();
573       $(not_editable_div_elt).show();
574       $(editable_div_elt).find(':input').prop("disabled", true);
575       $(not_editable_div_elt).find(':input').prop("disabled", false);
576     }
577
578     if (discount_str) {
579       var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
580       var html_elt     = $(row).find('[name="discount_text"]');
581       discount_elt.val(discount_str);
582       html_elt.html(discount_str);
583       ns.recalc_amounts_and_taxes();
584     }
585
586     kivi.io.close_dialog();
587   };
588
589   ns.show_periodic_invoices_config_dialog = function() {
590     if ($('#type').val() !== 'sales_order') return;
591
592     kivi.popup_dialog({
593       url:    'controller.pl?action=Order/show_periodic_invoices_config_dialog',
594       data:   { type:              $('#type').val(),
595                 id:                $('#id').val(),
596                 config:            $('#order_periodic_invoices_config').val(),
597                 customer_id:       $('#order_customer_id').val(),
598                 transdate_as_date: $('#order_transdate_as_date').val(),
599                 language_id:       $('#language_id').val()
600               },
601       id:     'jq_periodic_invoices_config_dialog',
602       load:   kivi.reinit_widgets,
603       dialog: {
604         title:  kivi.t8('Edit the configuration for periodic invoices'),
605         width:  800,
606         height: 650
607       }
608     });
609     return true;
610   };
611
612   ns.close_periodic_invoices_config_dialog = function() {
613     $('#jq_periodic_invoices_config_dialog').dialog('close');
614   };
615
616   ns.assign_periodic_invoices_config = function() {
617     var data = $('[name="Form"]').serializeArray();
618     data.push({ name: 'type',   value: $('#type').val() },
619               { name: 'action', value: 'Order/assign_periodic_invoices_config' });
620     $.post("controller.pl", data, kivi.eval_json_result);
621   };
622
623   ns.check_save_active_periodic_invoices = function() {
624     var type = $('#type').val();
625     if (type !== 'sales_order') return true;
626
627     var active = false;
628     $.ajax({
629       url:      'controller.pl',
630       data:     { action: 'Order/get_has_active_periodic_invoices',
631                   type  : type,
632                   id    : $('#id').val(),
633                   config: $('#order_periodic_invoices_config').val(),
634                 },
635       method:   "GET",
636       async:    false,
637       dataType: 'text',
638       success:  function(val) {
639         active = val;
640       }
641     });
642
643     if (active == 1) {
644       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?'));
645     }
646
647     return true;
648   };
649
650   ns.show_vc_details_dialog = function() {
651     if (!ns.check_cv()) return;
652     var vc;
653     var vc_id;
654     var title;
655     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
656       vc    = 'customer';
657       vc_id = $('#order_customer_id').val();
658       title = kivi.t8('Customer details');
659     } else {
660       vc    = 'vendor';
661       vc_id = $('#order_vendor_id').val();
662       title = kivi.t8('Vendor details');
663     }
664
665     kivi.popup_dialog({
666       url:    'controller.pl',
667       data:   { action: 'Order/show_customer_vendor_details_dialog',
668                 type  : $('#type').val(),
669                 vc    : vc,
670                 vc_id : vc_id
671               },
672       id:     'jq_customer_vendor_details_dialog',
673       dialog: {
674         title:  title,
675         width:  800,
676         height: 650
677       }
678     });
679     return true;
680   };
681
682   ns.update_row_from_master_data = function(clicked) {
683     var row = $(clicked).parents("tbody").first();
684     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
685
686     var data = $('#order_form').serializeArray();
687     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
688     data.push({ name: 'item_ids[]', value: item_id_dom.val() });
689
690     $.post("controller.pl", data, kivi.eval_json_result);
691   };
692
693   ns.update_all_rows_from_master_data = function() {
694     var item_ids = $.map($('.row_entry'), function(elt) {
695       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
696       return { name: 'item_ids[]', value: item_id };
697     });
698
699     if (item_ids.length == 0) {
700       return;
701     }
702
703     var data = $('#order_form').serializeArray();
704     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
705     data = data.concat(item_ids);
706
707     $.post("controller.pl", data, kivi.eval_json_result);
708   };
709
710   ns.show_calculate_qty_dialog = function(clicked) {
711     var row        = $(clicked).parents("tbody").first();
712     var input_id   = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
713     var formula_id = $(row).find('[name="formula[+]"]').attr('id');
714
715     calculate_qty_selection_dialog("", input_id, "", formula_id);
716     return true;
717   };
718
719   ns.edit_custom_shipto = function() {
720     if (!ns.check_cv()) return;
721
722     kivi.SalesPurchase.edit_custom_shipto();
723   };
724
725   ns.purchase_order_check_for_direct_delivery = function() {
726     if ($('#type').val() != 'sales_order') {
727       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
728     }
729
730     var empty = true;
731     var shipto;
732     if ($('#order_shipto_id').val() !== '') {
733       empty = false;
734       shipto = $('#order_shipto_id option:selected').text();
735     } else {
736       $('#shipto_inputs [id^="shipto"]').each(function(idx, elt) {
737         if (!empty)                                     return true;
738         if (/^shipto_to_copy/.test($(elt).prop('id')))  return true;
739         if (/^shiptocp_gender/.test($(elt).prop('id'))) return true;
740         if (/^shiptocvar_/.test($(elt).prop('id')))     return true;
741         if ($(elt).val() !== '') {
742           empty = false;
743           return false;
744         }
745       });
746       var shipto_elements = [];
747       $([$('#shiptoname').val(), $('#shiptostreet').val(), $('#shiptozipcode').val(), $('#shiptocity').val()]).each(function(idx, elt) {
748         if (elt !== '') shipto_elements.push(elt);
749       });
750       shipto = shipto_elements.join('; ');
751     }
752
753     var use_it = false;
754     if (!empty) {
755       ns.direct_delivery_dialog(shipto);
756     } else {
757       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
758     }
759   };
760
761   ns.direct_delivery_callback = function(accepted) {
762     $('#direct-delivery-dialog').dialog('close');
763
764     if (accepted) {
765       $('<input type="hidden" name="use_shipto">').appendTo('#order_form').val('1');
766     }
767
768     kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
769   };
770
771   ns.direct_delivery_dialog = function(shipto) {
772     $('#direct-delivery-dialog').remove();
773
774     var text1 = kivi.t8('You have entered or selected the following shipping address for this customer:');
775     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?');
776     var html  = '<div id="direct-delivery-dialog"><p>' + text1 + '</p><p>' + shipto + '</p><p>' + text2 + '</p>';
777     html      = html + '<hr><p>';
778     html      = html + '<input type="button" value="' + kivi.t8('Yes') + '" size="30" onclick="kivi.Order.direct_delivery_callback(true)">';
779     html      = html + '&nbsp;';
780     html      = html + '<input type="button" value="' + kivi.t8('No')  + '" size="30" onclick="kivi.Order.direct_delivery_callback(false)">';
781     html      = html + '</p></div>';
782     $(html).hide().appendTo('#order_form');
783
784     kivi.popup_dialog({id: 'direct-delivery-dialog',
785                        dialog: {title:  kivi.t8('Carry over shipping address'),
786                                 height: 300,
787                                 width:  500 }});
788   };
789
790   ns.follow_up_window = function() {
791     var id   = $('#id').val();
792     var type = $('#type').val();
793
794     var number_info = '';
795     if ($('#type').val() == 'sales_order' || $('#type').val() == 'purchase_order') {
796       number_info = $('#order_ordnumber').val();
797     } else if ($('#type').val() == 'sales_quotation' || $('#type').val() == 'request_quotation') {
798       number_info = $('#order_quonumber').val();
799     }
800
801     var name_info = '';
802     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation') {
803       name_info = $('#order_customer_id_name').val();
804     } else if ($('#type').val() == 'purchase_order' || $('#type').val() == 'request_quotation') {
805       name_info = $('#order_vendor_id_name').val();
806     }
807
808     var info = '';
809     if (number_info !== '') { info += ' (' + number_info + ')' }
810     if (name_info   !== '') { info += ' (' + name_info + ')' }
811
812     if (!$('#follow_up_rowcount').lenght) {
813       $('<input type="hidden" name="follow_up_rowcount"        id="follow_up_rowcount">').appendTo('#order_form');
814       $('<input type="hidden" name="follow_up_trans_id_1"      id="follow_up_trans_id_1">').appendTo('#order_form');
815       $('<input type="hidden" name="follow_up_trans_type_1"    id="follow_up_trans_type_1">').appendTo('#order_form');
816       $('<input type="hidden" name="follow_up_trans_info_1"    id="follow_up_trans_info_1">').appendTo('#order_form');
817       $('<input type="hidden" name="follow_up_trans_subject_1" id="follow_up_trans_subject_1">').appendTo('#order_form');
818     }
819     $('#follow_up_rowcount').val(1);
820     $('#follow_up_trans_id_1').val(id);
821     $('#follow_up_trans_type_1').val(type);
822     $('#follow_up_trans_info_1').val(info);
823     $('#follow_up_trans_subject_1').val($('#order_transaction_description').val());
824
825     follow_up_window();
826   };
827
828 });
829
830 $(function() {
831   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
832     $('#order_customer_id').change(kivi.Order.reload_cv_dependent_selections);
833   } else {
834     $('#order_vendor_id').change(kivi.Order.reload_cv_dependent_selections);
835   }
836
837   $('#order_currency_id').change(kivi.Order.update_exchangerate);
838   $('#order_transdate_as_date').change(kivi.Order.update_exchangerate);
839   $('#order_exchangerate_as_null_number').change(kivi.Order.exchangerate_changed);
840
841   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
842     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
843   } else {
844     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
845   }
846   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
847   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
848
849   $('.add_item_input').keydown(function(event) {
850     if (event.keyCode == 13) {
851       event.preventDefault();
852       kivi.Order.add_item();
853       return false;
854     }
855   });
856
857   kivi.Order.init_row_handlers();
858
859   $('#row_table_id').on('sortstop', function(event, ui) {
860     $('#row_table_id thead a img').remove();
861     kivi.Order.renumber_positions();
862   });
863
864   $('#expand_all').on('click', function(event) {
865     event.preventDefault();
866     if ($('#expand_all').data('expanded') == 1) {
867       $('#expand_all').data('expanded', 0);
868       $('#expand_all').attr('src', 'image/expand.svg');
869       $('#expand_all').attr('alt', kivi.t8('Show all details'));
870       $('#expand_all').attr('title', kivi.t8('Show all details'));
871       $('.row_entry').each(function(idx, elt) {
872         kivi.Order.hide_second_row(elt);
873       });
874     } else {
875       $('#expand_all').data('expanded', 1);
876       $('#expand_all').attr('src', "image/collapse.svg");
877       $('#expand_all').attr('alt', kivi.t8('Hide all details'));
878       $('#expand_all').attr('title', kivi.t8('Hide all details'));
879       kivi.Order.load_all_second_rows();
880       $('.row_entry').each(function(idx, elt) {
881         kivi.Order.show_second_row(elt);
882       });
883     }
884     return false;
885   });
886
887   $('.reformat_number_as_null_number').change(kivi.Order.reformat_number_as_null_number);
888
889 });