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.'));
 
   9       if ($('#order_vendor_id').val() === '') {
 
  10         alert(kivi.t8('Please select a vendor.'));
 
  17   ns.check_duplicate_parts = function(question) {
 
  18     var id_arr = $('[name="order.orderitems[].parts_id"]').map(function() { return this.value; }).get();
 
  20     var i, obj = {}, pos = [];
 
  22     for (i = 0; i < id_arr.length; i++) {
 
  24       if (obj.hasOwnProperty(id)) {
 
  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"
 
  39   ns.check_valid_reqdate = function() {
 
  40     if ($('#order_reqdate_as_date').val() === '') {
 
  41       alert(kivi.t8('Please select a delivery date.'));
 
  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;
 
  53     var data = $('#order_form').serializeArray();
 
  54     data.push({ name: 'action', value: 'Order/' + action });
 
  56     $.post("controller.pl", data, kivi.eval_json_result);
 
  59   ns.delete_order = function() {
 
  60     var data = $('#order_form').serializeArray();
 
  61     data.push({ name: 'action', value: 'Order/delete' });
 
  63     $.post("controller.pl", data, kivi.eval_json_result);
 
  66   ns.show_print_options = function(warn_on_duplicates, warn_on_reqdate) {
 
  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     if (warn_on_reqdate    && !ns.check_valid_reqdate())   return;
 
  74         title: kivi.t8('Print options'),
 
  81   ns.print = function() {
 
  82     $('#print_options').dialog('close');
 
  84     var data = $('#order_form').serializeArray();
 
  85     data = data.concat($('#print_options_form').serializeArray());
 
  86     data.push({ name: 'action', value: 'Order/print' });
 
  88     $.post("controller.pl", data, kivi.eval_json_result);
 
  93   ns.setup_send_email_dialog = function() {
 
  94     kivi.SalesPurchase.show_all_print_options_elements();
 
  95     kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false);
 
  97     $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
 
  99     $('select#format').change(kivi.Order.adjust_email_attachment_name_for_template_format);
 
 100     kivi.Order.adjust_email_attachment_name_for_template_format();
 
 102     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
 
 103     $('#email_form_' + to_focus).focus();
 
 106   ns.finish_send_email_dialog = function() {
 
 107     kivi.SalesPurchase.show_all_print_options_elements();
 
 109     $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
 
 113   ns.show_email_dialog = function(html) {
 
 114     var id            = 'send_email_dialog';
 
 115     var dialog_params = {
 
 119       title:  kivi.t8('Send email'),
 
 121       beforeClose: kivi.Order.finish_send_email_dialog,
 
 122       close: function(event, ui) {
 
 123         email_dialog.remove();
 
 127     $('#' + id).remove();
 
 129     email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
 
 130     email_dialog.html(html);
 
 131     email_dialog.dialog(dialog_params);
 
 133     kivi.Order.setup_send_email_dialog();
 
 135     $('.cancel').click(ns.close_email_dialog);
 
 140   ns.send_email = function() {
 
 141     // push button only once -> slow response from mail server
 
 142     ns.email_dialog_disable_send();
 
 144     var data = $('#order_form').serializeArray();
 
 145     data = data.concat($('[name^="email_form."]').serializeArray());
 
 146     data = data.concat($('[name^="print_options."]').serializeArray());
 
 147     data.push({ name: 'action', value: 'Order/send_email' });
 
 148     $.post("controller.pl", data, kivi.eval_json_result);
 
 151   ns.email_dialog_disable_send = function() {
 
 152     // disable mail send event to prevent
 
 153     // impatient users to send multiple times
 
 154     $('#send_email').prop('disabled', true);
 
 157   ns.close_email_dialog = function() {
 
 158     email_dialog.dialog("close");
 
 161   ns.adjust_email_attachment_name_for_template_format = function() {
 
 162     var $filename_elt = $('#email_form_attachment_filename');
 
 163     var $format_elt   = $('select#format');
 
 165     if (!$filename_elt || !$format_elt)
 
 168     var format   = $format_elt.val().toLowerCase();
 
 169     var new_ext  = format == 'html' ? 'html' : format == 'opendocument' ? 'odt' : 'pdf';
 
 170     var filename = $filename_elt.val();
 
 172     $filename_elt.val(filename.replace(/[^.]+$/, new_ext));
 
 175   ns.set_number_in_title = function(elt) {
 
 176     $('#nr_in_title').html($(elt).val());
 
 179   ns.reload_cv_dependent_selections = function() {
 
 180     $('#order_shipto_id').val('');
 
 181     var data = $('#order_form').serializeArray();
 
 182     data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
 
 184     $.post("controller.pl", data, kivi.eval_json_result);
 
 187   ns.reformat_number = function(event) {
 
 188     $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
 
 191   ns.reformat_number_as_null_number = function(event) {
 
 192     if ($(event.target).val() === '') {
 
 195     ns.reformat_number(event);
 
 198   ns.update_exchangerate = function(event) {
 
 199     if (!ns.check_cv()) {
 
 200       $('#order_currency_id').val($('#old_currency_id').val());
 
 204     var rate_input = $('#order_exchangerate_as_null_number');
 
 205     // unset exchangerate if currency changed
 
 206     if ($('#order_currency_id').val() !== $('#old_currency_id').val()) {
 
 210     // only set exchangerate if unset
 
 211     if (rate_input.val() !== '') {
 
 215     var data = $('#order_form').serializeArray();
 
 216     data.push({ name: 'action', value: 'Order/update_exchangerate' });
 
 219       url: 'controller.pl',
 
 223       success: function(data){
 
 224         if (!data.is_standard) {
 
 225           $('#currency_name').text(data.currency_name);
 
 226           if (data.exchangerate) {
 
 227             rate_input.val(data.exchangerate);
 
 231           $('#exchangerate_settings').show();
 
 234           $('#exchangerate_settings').hide();
 
 236         if ($('#order_currency_id').val() != $('#old_currency_id').val() ||
 
 237             !data.is_standard && data.exchangerate != $('#old_exchangerate').val()) {
 
 238           kivi.display_flash('warning', kivi.t8('You have changed the currency or exchange rate. Please check prices.'));
 
 240         $('#old_currency_id').val($('#order_currency_id').val());
 
 241         $('#old_exchangerate').val(data.exchangerate);
 
 246   ns.exchangerate_changed = function(event) {
 
 247     if (kivi.parse_amount($('#order_exchangerate_as_null_number').val()) != kivi.parse_amount($('#old_exchangerate').val())) {
 
 248       kivi.display_flash('warning', kivi.t8('You have changed the currency or exchange rate. Please check prices.'));
 
 249       $('#old_exchangerate').val($('#order_exchangerate_as_null_number').val());
 
 253   ns.recalc_amounts_and_taxes = function() {
 
 254     if (!kivi.validate_form('#order_form')) return;
 
 256     var data = $('#order_form').serializeArray();
 
 257     data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
 
 259     $.post("controller.pl", data, kivi.eval_json_result);
 
 262   ns.unit_change = function(event) {
 
 263     var row           = $(event.target).parents("tbody").first();
 
 264     var item_id_dom   = $(row).find('[name="orderitem_ids[+]"]');
 
 265     var sellprice_dom = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 266     var select_elt    = $(row).find('[name="order.orderitems[].unit"]');
 
 268     var oldval = $(select_elt).data('oldval');
 
 269     $(select_elt).data('oldval', $(select_elt).val());
 
 271     var data = $('#order_form').serializeArray();
 
 272     data.push({ name: 'action',           value: 'Order/unit_changed'     },
 
 273               { name: 'item_id',          value: item_id_dom.val()        },
 
 274               { name: 'old_unit',         value: oldval                   },
 
 275               { name: 'sellprice_dom_id', value: sellprice_dom.attr('id') });
 
 277     $.post("controller.pl", data, kivi.eval_json_result);
 
 280   ns.update_sellprice = function(item_id, price_str) {
 
 281     var row       = $('#item_' + item_id).parents("tbody").first();
 
 282     var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 283     var html_elt  = $(row).find('[name="sellprice_text"]');
 
 284     price_elt.val(price_str);
 
 285     html_elt.html(price_str);
 
 288   ns.load_second_row = function(row) {
 
 289     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 290     var div_elt     = $(row).find('[name="second_row"]');
 
 292     if ($(div_elt).data('loaded') == 1) {
 
 295     var data = $('#order_form').serializeArray();
 
 296     data.push({ name: 'action',     value: 'Order/load_second_rows' },
 
 297               { name: 'item_ids[]', value: item_id_dom.val()        });
 
 299     $.post("controller.pl", data, kivi.eval_json_result);
 
 302   ns.load_all_second_rows = function() {
 
 303     var rows = $('.row_entry').filter(function(idx, elt) {
 
 304       return $(elt).find('[name="second_row"]').data('loaded') != 1;
 
 307     var item_ids = $.map(rows, function(elt) {
 
 308       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
 
 309       return { name: 'item_ids[]', value: item_id };
 
 312     if (item_ids.length == 0) {
 
 316     var data = $('#order_form').serializeArray();
 
 317     data.push({ name: 'action', value: 'Order/load_second_rows' });
 
 318     data = data.concat(item_ids);
 
 320     $.post("controller.pl", data, kivi.eval_json_result);
 
 323   ns.hide_second_row = function(row) {
 
 324     $(row).children().not(':first').hide();
 
 325     $(row).data('expanded', 0);
 
 326     var elt = $(row).find('.expand');
 
 327     elt.attr('src', "image/expand.svg");
 
 328     elt.attr('alt', kivi.t8('Show details'));
 
 329     elt.attr('title', kivi.t8('Show details'));
 
 332   ns.show_second_row = function(row) {
 
 333     $(row).children().not(':first').show();
 
 334     $(row).data('expanded', 1);
 
 335     var elt = $(row).find('.expand');
 
 336     elt.attr('src', "image/collapse.svg");
 
 337     elt.attr('alt', kivi.t8('Hide details'));
 
 338     elt.attr('title', kivi.t8('Hide details'));
 
 341   ns.toggle_second_row = function(row) {
 
 342     if ($(row).data('expanded') == 1) {
 
 343       ns.hide_second_row(row);
 
 345       ns.show_second_row(row);
 
 349   ns.init_row_handlers = function() {
 
 350     kivi.run_once_for('.recalc', 'on_change_recalc', function(elt) {
 
 351       $(elt).change(ns.recalc_amounts_and_taxes);
 
 354     kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
 
 355       $(elt).change(ns.reformat_number);
 
 358     kivi.run_once_for('.unitselect', 'on_change_unit_with_oldval', function(elt) {
 
 359       $(elt).data('oldval', $(elt).val());
 
 360       $(elt).change(ns.unit_change);
 
 363     kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
 
 364       $(elt).keydown(function(event) {
 
 366         if (event.keyCode == 40 && event.shiftKey === true) {
 
 368           event.preventDefault();
 
 369           row = $(event.target).parents(".row_entry").first();
 
 370           ns.load_second_row(row);
 
 371           ns.show_second_row(row);
 
 374         if (event.keyCode == 38 && event.shiftKey === true) {
 
 376           event.preventDefault();
 
 377           row = $(event.target).parents(".row_entry").first();
 
 378           ns.hide_second_row(row);
 
 384     kivi.run_once_for('.expand', 'expand_second_row', function(elt) {
 
 385       $(elt).click(function(event) {
 
 386         event.preventDefault();
 
 387         var row = $(event.target).parents(".row_entry").first();
 
 388         ns.load_second_row(row);
 
 389         ns.toggle_second_row(row);
 
 396   ns.redisplay_line_values = function(is_sales, data) {
 
 397     $('.row_entry').each(function(idx, elt) {
 
 398       $(elt).find('[name="linetotal"]').html(data[idx][0]);
 
 399       if (is_sales && $(elt).find('[name="second_row"]').data('loaded') == 1) {
 
 400         var mt = data[idx][1];
 
 401         var mp = data[idx][2];
 
 403         if (mt[0] === '-') h += ' class="plus0"';
 
 404         h += '>' + mt + '  ' + mp + '%';
 
 406         $(elt).find('[name="linemargin"]').html(h);
 
 411   ns.redisplay_cvpartnumbers = function(data) {
 
 412     $('.row_entry').each(function(idx, elt) {
 
 413       $(elt).find('[name="cvpartnumber"]').html(data[idx][0]);
 
 417   ns.renumber_positions = function() {
 
 418     $('.row_entry [name="position"]').each(function(idx, elt) {
 
 421     $('.row_entry').each(function(idx, elt) {
 
 422       $(elt).data("position", idx+1);
 
 426   ns.reorder_items = function(order_by) {
 
 427     var dir = $('#' + order_by + '_header_id a img').attr("data-sort-dir");
 
 428     $('#row_table_id thead a img').remove();
 
 433       src = "image/up.png";
 
 436       src = "image/down.png";
 
 439     $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
 
 441     var data = $('#order_form').serializeArray();
 
 442     data.push({ name: 'action',   value: 'Order/reorder_items' },
 
 443               { name: 'order_by', value: order_by              },
 
 444               { name: 'sort_dir', value: dir                   });
 
 446     $.post("controller.pl", data, kivi.eval_json_result);
 
 449   ns.redisplay_items = function(data) {
 
 450     var old_rows = $('.row_entry').detach();
 
 452     $(data).each(function(idx, elt) {
 
 453       new_rows.push(old_rows[elt.old_pos - 1]);
 
 455     $(new_rows).appendTo($('#row_table_id'));
 
 456     ns.renumber_positions();
 
 459   ns.get_insert_before_item_id = function(wanted_pos) {
 
 460     if (wanted_pos === '') return;
 
 462     var insert_before_item_id;
 
 463     // selection by data does not seem to work if data is changed at runtime
 
 464     // var elt = $('.row_entry [data-position="' + wanted_pos + '"]');
 
 465     $('.row_entry').each(function(idx, elt) {
 
 466       if ($(elt).data("position") == wanted_pos) {
 
 467         insert_before_item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
 
 472     return insert_before_item_id;
 
 475   ns.add_item = function() {
 
 476     if ($('#add_item_parts_id').val() === '') return;
 
 477     if (!ns.check_cv()) return;
 
 479     $('#row_table_id thead a img').remove();
 
 481     var insert_before_item_id = ns.get_insert_before_item_id($('#add_item_position').val());
 
 483     var data = $('#order_form').serializeArray();
 
 484     data.push({ name: 'action', value: 'Order/add_item' },
 
 485               { name: 'insert_before_item_id', value: insert_before_item_id });
 
 487     $.post("controller.pl", data, kivi.eval_json_result);
 
 490   ns.open_multi_items_dialog = function() {
 
 491     if (!ns.check_cv()) return;
 
 493     var pp = $("#add_item_parts_id").data("part_picker");
 
 498   ns.add_multi_items = function(data) {
 
 499     var insert_before_item_id = ns.get_insert_before_item_id($('#multi_items_position').val());
 
 500     data = data.concat($('#order_form').serializeArray());
 
 501     data.push({ name: 'action', value: 'Order/add_multi_items' },
 
 502               { name: 'insert_before_item_id', value: insert_before_item_id });
 
 503     $.post("controller.pl", data, kivi.eval_json_result);
 
 506   ns.delete_order_item_row = function(clicked) {
 
 507     var row = $(clicked).parents("tbody").first();
 
 510     ns.renumber_positions();
 
 511     ns.recalc_amounts_and_taxes();
 
 514   ns.row_table_scroll_down = function() {
 
 515     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
 
 518   ns.show_longdescription_dialog = function(clicked) {
 
 519     var row                 = $(clicked).parents("tbody").first();
 
 520     var position            = $(row).find('[name="position"]').html();
 
 521     var partnumber          = $(row).find('[name="partnumber"]').html();
 
 522     var description_elt     = $(row).find('[name="order.orderitems[].description"]');
 
 523     var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
 
 526       runningnumber:           position,
 
 527       partnumber:              partnumber,
 
 528       description:             description_elt.val(),
 
 529       default_longdescription: longdescription_elt.val(),
 
 530       set_function:            function(val) {
 
 531         longdescription_elt.val(val);
 
 535     kivi.SalesPurchase.edit_longdescription_with_params(params);
 
 538   ns.price_chooser_item_row = function(clicked) {
 
 539     if (!ns.check_cv()) return;
 
 540     var row         = $(clicked).parents("tbody").first();
 
 541     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 543     var data = $('#order_form').serializeArray();
 
 544     data.push({ name: 'action',  value: 'Order/price_popup' },
 
 545               { name: 'item_id', value: item_id_dom.val()   });
 
 547     $.post("controller.pl", data, kivi.eval_json_result);
 
 550   ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
 
 551     var row        = $('#item_' + item_id).parents("tbody").first();
 
 552     var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
 
 553     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 555     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
 
 556     source_elt.val(source);
 
 558     var editable_div_elt     = $(row).find('[name="editable_price"]');
 
 559     var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
 
 560     if (price_editable == 1 && source === '') {
 
 562       $(editable_div_elt).show();
 
 563       $(not_editable_div_elt).hide();
 
 564       $(editable_div_elt).find(':input').prop("disabled", false);
 
 565       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 568       $(editable_div_elt).hide();
 
 569       $(not_editable_div_elt).show();
 
 570       $(editable_div_elt).find(':input').prop("disabled", true);
 
 571       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 575       var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 576       var html_elt  = $(row).find('[name="sellprice_text"]');
 
 577       price_elt.val(price_str);
 
 578       html_elt.html(price_str);
 
 579       ns.recalc_amounts_and_taxes();
 
 582     kivi.io.close_dialog();
 
 585   ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
 
 586     var row        = $('#item_' + item_id).parents("tbody").first();
 
 587     var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
 
 588     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 590     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
 
 591     source_elt.val(source);
 
 593     var editable_div_elt     = $(row).find('[name="editable_discount"]');
 
 594     var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
 
 595     if (price_editable == 1 && source === '') {
 
 597       $(editable_div_elt).show();
 
 598       $(not_editable_div_elt).hide();
 
 599       $(editable_div_elt).find(':input').prop("disabled", false);
 
 600       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 603       $(editable_div_elt).hide();
 
 604       $(not_editable_div_elt).show();
 
 605       $(editable_div_elt).find(':input').prop("disabled", true);
 
 606       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 610       var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
 
 611       var html_elt     = $(row).find('[name="discount_text"]');
 
 612       discount_elt.val(discount_str);
 
 613       html_elt.html(discount_str);
 
 614       ns.recalc_amounts_and_taxes();
 
 617     kivi.io.close_dialog();
 
 620   ns.show_periodic_invoices_config_dialog = function() {
 
 621     if ($('#type').val() !== 'sales_order') return;
 
 624       url:    'controller.pl?action=Order/show_periodic_invoices_config_dialog',
 
 625       data:   { type:              $('#type').val(),
 
 627                 config:            $('#order_periodic_invoices_config').val(),
 
 628                 customer_id:       $('#order_customer_id').val(),
 
 629                 transdate_as_date: $('#order_transdate_as_date').val(),
 
 630                 language_id:       $('#language_id').val()
 
 632       id:     'jq_periodic_invoices_config_dialog',
 
 633       load:   kivi.reinit_widgets,
 
 635         title:  kivi.t8('Edit the configuration for periodic invoices'),
 
 643   ns.close_periodic_invoices_config_dialog = function() {
 
 644     $('#jq_periodic_invoices_config_dialog').dialog('close');
 
 647   ns.assign_periodic_invoices_config = function() {
 
 648     var data = $('[name="Form"]').serializeArray();
 
 649     data.push({ name: 'type',   value: $('#type').val() },
 
 650               { name: 'action', value: 'Order/assign_periodic_invoices_config' });
 
 651     $.post("controller.pl", data, kivi.eval_json_result);
 
 654   ns.check_save_active_periodic_invoices = function() {
 
 655     var type = $('#type').val();
 
 656     if (type !== 'sales_order') return true;
 
 660       url:      'controller.pl',
 
 661       data:     { action: 'Order/get_has_active_periodic_invoices',
 
 664                   config: $('#order_periodic_invoices_config').val(),
 
 669       success:  function(val) {
 
 675       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?'));
 
 681   ns.show_vc_details_dialog = function() {
 
 682     if (!ns.check_cv()) return;
 
 686     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 688       vc_id = $('#order_customer_id').val();
 
 689       title = kivi.t8('Customer details');
 
 692       vc_id = $('#order_vendor_id').val();
 
 693       title = kivi.t8('Vendor details');
 
 697       url:    'controller.pl',
 
 698       data:   { action: 'Order/show_customer_vendor_details_dialog',
 
 699                 type  : $('#type').val(),
 
 703       id:     'jq_customer_vendor_details_dialog',
 
 713   ns.update_row_from_master_data = function(clicked) {
 
 714     var row = $(clicked).parents("tbody").first();
 
 715     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 717     var data = $('#order_form').serializeArray();
 
 718     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
 
 719     data.push({ name: 'item_ids[]', value: item_id_dom.val() });
 
 721     $.post("controller.pl", data, kivi.eval_json_result);
 
 724   ns.update_all_rows_from_master_data = function() {
 
 725     var item_ids = $.map($('.row_entry'), function(elt) {
 
 726       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
 
 727       return { name: 'item_ids[]', value: item_id };
 
 730     if (item_ids.length == 0) {
 
 734     var data = $('#order_form').serializeArray();
 
 735     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
 
 736     data = data.concat(item_ids);
 
 738     $.post("controller.pl", data, kivi.eval_json_result);
 
 741   ns.show_calculate_qty_dialog = function(clicked) {
 
 742     var row        = $(clicked).parents("tbody").first();
 
 743     var input_id   = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
 
 744     var formula_id = $(row).find('[name="formula[+]"]').attr('id');
 
 746     calculate_qty_selection_dialog("", input_id, "", formula_id);
 
 750   ns.edit_custom_shipto = function() {
 
 751     if (!ns.check_cv()) return;
 
 753     kivi.SalesPurchase.edit_custom_shipto();
 
 756   ns.purchase_order_check_for_direct_delivery = function() {
 
 757     if ($('#type').val() != 'sales_order') {
 
 758       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 763     if ($('#order_shipto_id').val() !== '') {
 
 765       shipto = $('#order_shipto_id option:selected').text();
 
 767       $('#shipto_inputs [id^="shipto"]').each(function(idx, elt) {
 
 768         if (!empty)                                     return true;
 
 769         if (/^shipto_to_copy/.test($(elt).prop('id')))  return true;
 
 770         if (/^shiptocp_gender/.test($(elt).prop('id'))) return true;
 
 771         if (/^shiptocvar_/.test($(elt).prop('id')))     return true;
 
 772         if ($(elt).val() !== '') {
 
 777       var shipto_elements = [];
 
 778       $([$('#shiptoname').val(), $('#shiptostreet').val(), $('#shiptozipcode').val(), $('#shiptocity').val()]).each(function(idx, elt) {
 
 779         if (elt !== '') shipto_elements.push(elt);
 
 781       shipto = shipto_elements.join('; ');
 
 786       ns.direct_delivery_dialog(shipto);
 
 788       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 792   ns.direct_delivery_callback = function(accepted) {
 
 793     $('#direct-delivery-dialog').dialog('close');
 
 796       $('<input type="hidden" name="use_shipto">').appendTo('#order_form').val('1');
 
 799     kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 802   ns.direct_delivery_dialog = function(shipto) {
 
 803     $('#direct-delivery-dialog').remove();
 
 805     var text1 = kivi.t8('You have entered or selected the following shipping address for this customer:');
 
 806     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?');
 
 807     var html  = '<div id="direct-delivery-dialog"><p>' + text1 + '</p><p>' + shipto + '</p><p>' + text2 + '</p>';
 
 808     html      = html + '<hr><p>';
 
 809     html      = html + '<input type="button" value="' + kivi.t8('Yes') + '" size="30" onclick="kivi.Order.direct_delivery_callback(true)">';
 
 810     html      = html + ' ';
 
 811     html      = html + '<input type="button" value="' + kivi.t8('No')  + '" size="30" onclick="kivi.Order.direct_delivery_callback(false)">';
 
 812     html      = html + '</p></div>';
 
 813     $(html).hide().appendTo('#order_form');
 
 815     kivi.popup_dialog({id: 'direct-delivery-dialog',
 
 816                        dialog: {title:  kivi.t8('Carry over shipping address'),
 
 821   ns.follow_up_window = function() {
 
 822     var id   = $('#id').val();
 
 823     var type = $('#type').val();
 
 825     var number_info = '';
 
 826     if ($('#type').val() == 'sales_order' || $('#type').val() == 'purchase_order') {
 
 827       number_info = $('#order_ordnumber').val();
 
 828     } else if ($('#type').val() == 'sales_quotation' || $('#type').val() == 'request_quotation') {
 
 829       number_info = $('#order_quonumber').val();
 
 833     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation') {
 
 834       name_info = $('#order_customer_id_name').val();
 
 835     } else if ($('#type').val() == 'purchase_order' || $('#type').val() == 'request_quotation') {
 
 836       name_info = $('#order_vendor_id_name').val();
 
 840     if (number_info !== '') { info += ' (' + number_info + ')' }
 
 841     if (name_info   !== '') { info += ' (' + name_info + ')' }
 
 843     if (!$('#follow_up_rowcount').length) {
 
 844       $('<input type="hidden" name="follow_up_rowcount"        id="follow_up_rowcount">').appendTo('#order_form');
 
 845       $('<input type="hidden" name="follow_up_trans_id_1"      id="follow_up_trans_id_1">').appendTo('#order_form');
 
 846       $('<input type="hidden" name="follow_up_trans_type_1"    id="follow_up_trans_type_1">').appendTo('#order_form');
 
 847       $('<input type="hidden" name="follow_up_trans_info_1"    id="follow_up_trans_info_1">').appendTo('#order_form');
 
 848       $('<input type="hidden" name="follow_up_trans_subject_1" id="follow_up_trans_subject_1">').appendTo('#order_form');
 
 850     $('#follow_up_rowcount').val(1);
 
 851     $('#follow_up_trans_id_1').val(id);
 
 852     $('#follow_up_trans_type_1').val(type);
 
 853     $('#follow_up_trans_info_1').val(info);
 
 854     $('#follow_up_trans_subject_1').val($('#order_transaction_description').val());
 
 859   ns.create_part = function() {
 
 860     var data = $('#order_form').serializeArray();
 
 861     data.push({ name: 'action', value: 'Order/create_part' });
 
 863     $.post("controller.pl", data, kivi.eval_json_result);
 
 866   ns.check_transport_cost_article_presence = function() {
 
 867     var $form          = $('#order_form');
 
 868     var wanted_part_id = $form.data('transport-cost-reminder-article-id');
 
 870     if (!wanted_part_id) return true
 
 872     var id_arr = $('[name="order.orderitems[].parts_id"]').map(function() { return this.value; }).get();
 
 873     id_arr = $.grep(id_arr, function(elt) {
 
 874       return ((elt*1) === wanted_part_id);
 
 877     if (id_arr.length) return true;
 
 879     var description = $form.data('transport-cost-reminder-article-description');
 
 880     return confirm(kivi.t8("The transport cost article '#1' is missing. Do you want to continue anyway?", [ description ]));
 
 883   ns.check_cusordnumber_presence = function() {
 
 884     if ($('#order_cusordnumber').val() === '') {
 
 885       return confirm(kivi.t8('The customer order number is missing. Do you want to continue anyway?'));
 
 893   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 894     $('#order_customer_id').change(kivi.Order.reload_cv_dependent_selections);
 
 896     $('#order_vendor_id').change(kivi.Order.reload_cv_dependent_selections);
 
 899   $('#order_currency_id').change(kivi.Order.update_exchangerate);
 
 900   $('#order_transdate_as_date').change(kivi.Order.update_exchangerate);
 
 901   $('#order_exchangerate_as_null_number').change(kivi.Order.exchangerate_changed);
 
 903   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 904     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
 
 906     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
 
 908   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
 
 909   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
 
 911   $('.add_item_input').keydown(function(event) {
 
 912     if (event.keyCode == 13) {
 
 913       event.preventDefault();
 
 914       kivi.Order.add_item();
 
 919   kivi.Order.init_row_handlers();
 
 921   $('#row_table_id').on('sortstop', function(event, ui) {
 
 922     $('#row_table_id thead a img').remove();
 
 923     kivi.Order.renumber_positions();
 
 926   $('#expand_all').on('click', function(event) {
 
 927     event.preventDefault();
 
 928     if ($('#expand_all').data('expanded') == 1) {
 
 929       $('#expand_all').data('expanded', 0);
 
 930       $('#expand_all').attr('src', 'image/expand.svg');
 
 931       $('#expand_all').attr('alt', kivi.t8('Show all details'));
 
 932       $('#expand_all').attr('title', kivi.t8('Show all details'));
 
 933       $('.row_entry').each(function(idx, elt) {
 
 934         kivi.Order.hide_second_row(elt);
 
 937       $('#expand_all').data('expanded', 1);
 
 938       $('#expand_all').attr('src', "image/collapse.svg");
 
 939       $('#expand_all').attr('alt', kivi.t8('Hide all details'));
 
 940       $('#expand_all').attr('title', kivi.t8('Hide all details'));
 
 941       kivi.Order.load_all_second_rows();
 
 942       $('.row_entry').each(function(idx, elt) {
 
 943         kivi.Order.show_second_row(elt);
 
 949   $('.reformat_number_as_null_number').change(kivi.Order.reformat_number_as_null_number);