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