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) {
 
  67     if (!ns.check_cv()) return;
 
  68     if (warn_on_duplicates && !ns.check_duplicate_parts(kivi.t8("Do you really want to print?"))) return;
 
  73         title: kivi.t8('Print options'),
 
  80   ns.print = function() {
 
  81     $('#print_options').dialog('close');
 
  83     var data = $('#order_form').serializeArray();
 
  84     data = data.concat($('#print_options_form').serializeArray());
 
  85     data.push({ name: 'action', value: 'Order/print' });
 
  87     $.post("controller.pl", data, kivi.eval_json_result);
 
  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);
 
  96     $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
 
  98     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
 
  99     $('#email_form_' + to_focus).focus();
 
 102   ns.finish_send_email_dialog = function() {
 
 103     kivi.SalesPurchase.show_all_print_options_elements();
 
 105     $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
 
 109   ns.show_email_dialog = function(html) {
 
 110     var id            = 'send_email_dialog';
 
 111     var dialog_params = {
 
 115       title:  kivi.t8('Send email'),
 
 117       beforeClose: kivi.Order.finish_send_email_dialog,
 
 118       close: function(event, ui) {
 
 119         email_dialog.remove();
 
 123     $('#' + id).remove();
 
 125     email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
 
 126     email_dialog.html(html);
 
 127     email_dialog.dialog(dialog_params);
 
 129     kivi.Order.setup_send_email_dialog();
 
 131     $('.cancel').click(ns.close_email_dialog);
 
 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);
 
 144   ns.close_email_dialog = function() {
 
 145     email_dialog.dialog("close");
 
 148   ns.set_number_in_title = function(elt) {
 
 149     $('#nr_in_title').html($(elt).val());
 
 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' });
 
 157     $.post("controller.pl", data, kivi.eval_json_result);
 
 160   ns.reformat_number = function(event) {
 
 161     $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
 
 164   ns.reformat_number_as_null_number = function(event) {
 
 165     if ($(event.target).val() === '') {
 
 168     ns.reformat_number(event);
 
 171   ns.update_exchangerate = function(event) {
 
 172     if (!ns.check_cv()) {
 
 173       $('#order_currency_id').val($('#old_currency_id').val());
 
 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()) {
 
 183     // only set exchangerate if unset
 
 184     if (rate_input.val() !== '') {
 
 188     var data = $('#order_form').serializeArray();
 
 189     data.push({ name: 'action', value: 'Order/update_exchangerate' });
 
 192       url: 'controller.pl',
 
 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);
 
 204           $('#exchangerate_settings').show();
 
 207           $('#exchangerate_settings').hide();
 
 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.'));
 
 213         $('#old_currency_id').val($('#order_currency_id').val());
 
 214         $('#old_exchangerate').val(data.exchangerate);
 
 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());
 
 226   ns.recalc_amounts_and_taxes = function() {
 
 227     var data = $('#order_form').serializeArray();
 
 228     data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
 
 230     $.post("controller.pl", data, kivi.eval_json_result);
 
 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"]');
 
 239     var oldval = $(select_elt).data('oldval');
 
 240     $(select_elt).data('oldval', $(select_elt).val());
 
 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') });
 
 248     $.post("controller.pl", data, kivi.eval_json_result);
 
 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);
 
 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"]');
 
 263     if ($(div_elt).data('loaded') == 1) {
 
 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()        });
 
 270     $.post("controller.pl", data, kivi.eval_json_result);
 
 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;
 
 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 };
 
 283     if (item_ids.length == 0) {
 
 287     var data = $('#order_form').serializeArray();
 
 288     data.push({ name: 'action', value: 'Order/load_second_rows' });
 
 289     data = data.concat(item_ids);
 
 291     $.post("controller.pl", data, kivi.eval_json_result);
 
 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'));
 
 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'));
 
 312   ns.toggle_second_row = function(row) {
 
 313     if ($(row).data('expanded') == 1) {
 
 314       ns.hide_second_row(row);
 
 316       ns.show_second_row(row);
 
 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);
 
 325     kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
 
 326       $(elt).change(ns.reformat_number);
 
 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);
 
 334     kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
 
 335       $(elt).keydown(function(event) {
 
 337         if (event.keyCode == 40 && event.shiftKey === true) {
 
 339           event.preventDefault();
 
 340           row = $(event.target).parents(".row_entry").first();
 
 341           ns.load_second_row(row);
 
 342           ns.show_second_row(row);
 
 345         if (event.keyCode == 38 && event.shiftKey === true) {
 
 347           event.preventDefault();
 
 348           row = $(event.target).parents(".row_entry").first();
 
 349           ns.hide_second_row(row);
 
 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);
 
 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];
 
 374         if (mt[0] === '-') h += ' class="plus0"';
 
 375         h += '>' + mt + '  ' + mp + '%';
 
 377         $(elt).find('[name="linemargin"]').html(h);
 
 382   ns.redisplay_cvpartnumbers = function(data) {
 
 383     $('.row_entry').each(function(idx, elt) {
 
 384       $(elt).find('[name="cvpartnumber"]').html(data[idx][0]);
 
 388   ns.renumber_positions = function() {
 
 389     $('.row_entry [name="position"]').each(function(idx, elt) {
 
 392     $('.row_entry').each(function(idx, elt) {
 
 393       $(elt).data("position", idx+1);
 
 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();
 
 404       src = "image/up.png";
 
 407       src = "image/down.png";
 
 410     $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
 
 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                   });
 
 417     $.post("controller.pl", data, kivi.eval_json_result);
 
 420   ns.redisplay_items = function(data) {
 
 421     var old_rows = $('.row_entry').detach();
 
 423     $(data).each(function(idx, elt) {
 
 424       new_rows.push(old_rows[elt.old_pos - 1]);
 
 426     $(new_rows).appendTo($('#row_table_id'));
 
 427     ns.renumber_positions();
 
 430   ns.get_insert_before_item_id = function(wanted_pos) {
 
 431     if (wanted_pos === '') return;
 
 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();
 
 443     return insert_before_item_id;
 
 446   ns.add_item = function() {
 
 447     if ($('#add_item_parts_id').val() === '') return;
 
 448     if (!ns.check_cv()) return;
 
 450     $('#row_table_id thead a img').remove();
 
 452     var insert_before_item_id = ns.get_insert_before_item_id($('#add_item_position').val());
 
 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 });
 
 458     $.post("controller.pl", data, kivi.eval_json_result);
 
 461   ns.setup_multi_items_dialog = function() {
 
 462     $('#multi_items_filter_table input, #multi_items_filter_table select').keydown(function(event) {
 
 463       if (event.keyCode == 13) {
 
 464         event.preventDefault();
 
 465         ns.multi_items_dialog_update_result();
 
 470     $('#multi_items_filter_all_substr_multi_ilike').focus();
 
 473   ns.show_multi_items_dialog = function() {
 
 474     if (!ns.check_cv()) return;
 
 476     $('#row_table_id thead a img').remove();
 
 479       url:    'controller.pl?action=Order/show_multi_items_dialog',
 
 480       data:   { type: $('#type').val() },
 
 481       id:     'jq_multi_items_dialog',
 
 482       load:   kivi.Order.setup_multi_items_dialog,
 
 484         title:  kivi.t8('Add multiple items'),
 
 492   ns.close_multi_items_dialog = function() {
 
 493     $('#jq_multi_items_dialog').dialog('close');
 
 496   ns.multi_items_dialog_update_result = function() {
 
 497     var data = $('#multi_items_form').serializeArray();
 
 498     data.push({ name: 'type', value: $('#type').val() });
 
 500       url:     'controller.pl?action=Order/multi_items_update_result',
 
 503       success: function(data) {
 
 504         $('#multi_items_result').html(data);
 
 505         ns.multi_items_dialog_enable_continue();
 
 506         ns.multi_items_result_setup_events();
 
 511   ns.multi_items_dialog_disable_continue = function() {
 
 512     // disable keydown-event and continue button to prevent
 
 513     // impatient users to add parts multiple times
 
 514     $('#multi_items_result input, #multi_items_position').off("keydown");
 
 515     $('#multi_items_dialog_continue_button').prop('disabled', true);
 
 518   ns.multi_items_dialog_enable_continue = function()  {
 
 519     $('#multi_items_result input, #multi_items_position').keydown(function(event) {
 
 520       if(event.keyCode == 13) {
 
 521         event.preventDefault();
 
 522         ns.add_multi_items();
 
 526     $('#multi_items_dialog_continue_button').prop('disabled', false);
 
 529   ns.multi_items_result_setup_events = function() {
 
 530     $('#multi_items_all_qty').change(ns.reformat_number);
 
 531     $('#multi_items_all_qty').change(function(event) {
 
 532       $('.multi_items_qty').val($(event.target).val());
 
 534     $('.multi_items_qty').change(ns.reformat_number);
 
 537   ns.add_multi_items = function() {
 
 539     var n_rows = $('.multi_items_qty').length;
 
 540     if (n_rows == 0) return;
 
 543     n_rows = $('.multi_items_qty').filter(function() {
 
 544       return $(this).val().length > 0;
 
 546     if (n_rows == 0) return;
 
 548     ns.multi_items_dialog_disable_continue();
 
 550     var insert_before_item_id = ns.get_insert_before_item_id($('#multi_items_position').val());
 
 552     var data = $('#order_form').serializeArray();
 
 553     data = data.concat($('#multi_items_form').serializeArray());
 
 554     data.push({ name: 'action', value: 'Order/add_multi_items' },
 
 555               { name: 'insert_before_item_id', value: insert_before_item_id });
 
 556     $.post("controller.pl", data, kivi.eval_json_result);
 
 559   ns.set_input_to_one = function(clicked) {
 
 560     if ($(clicked).val() == '') {
 
 561       $(clicked).val(kivi.format_amount(1.00, -2));
 
 566   ns.delete_order_item_row = function(clicked) {
 
 567     var row = $(clicked).parents("tbody").first();
 
 570     ns.renumber_positions();
 
 571     ns.recalc_amounts_and_taxes();
 
 574   ns.row_table_scroll_down = function() {
 
 575     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
 
 578   ns.show_longdescription_dialog = function(clicked) {
 
 579     var row                 = $(clicked).parents("tbody").first();
 
 580     var position            = $(row).find('[name="position"]').html();
 
 581     var partnumber          = $(row).find('[name="partnumber"]').html();
 
 582     var description_elt     = $(row).find('[name="order.orderitems[].description"]');
 
 583     var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
 
 586       runningnumber:           position,
 
 587       partnumber:              partnumber,
 
 588       description:             description_elt.val(),
 
 589       default_longdescription: longdescription_elt.val(),
 
 590       set_function:            function(val) {
 
 591         longdescription_elt.val(val);
 
 595     kivi.SalesPurchase.edit_longdescription_with_params(params);
 
 598   ns.price_chooser_item_row = function(clicked) {
 
 599     if (!ns.check_cv()) return;
 
 600     var row         = $(clicked).parents("tbody").first();
 
 601     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 603     var data = $('#order_form').serializeArray();
 
 604     data.push({ name: 'action',  value: 'Order/price_popup' },
 
 605               { name: 'item_id', value: item_id_dom.val()   });
 
 607     $.post("controller.pl", data, kivi.eval_json_result);
 
 610   ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
 
 611     var row        = $('#item_' + item_id).parents("tbody").first();
 
 612     var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
 
 613     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 615     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
 
 616     source_elt.val(source);
 
 618     var editable_div_elt     = $(row).find('[name="editable_price"]');
 
 619     var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
 
 620     if (price_editable == 1 && source === '') {
 
 622       $(editable_div_elt).show();
 
 623       $(not_editable_div_elt).hide();
 
 624       $(editable_div_elt).find(':input').prop("disabled", false);
 
 625       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 628       $(editable_div_elt).hide();
 
 629       $(not_editable_div_elt).show();
 
 630       $(editable_div_elt).find(':input').prop("disabled", true);
 
 631       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 635       var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 636       var html_elt  = $(row).find('[name="sellprice_text"]');
 
 637       price_elt.val(price_str);
 
 638       html_elt.html(price_str);
 
 639       ns.recalc_amounts_and_taxes();
 
 642     kivi.io.close_dialog();
 
 645   ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
 
 646     var row        = $('#item_' + item_id).parents("tbody").first();
 
 647     var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
 
 648     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 650     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
 
 651     source_elt.val(source);
 
 653     var editable_div_elt     = $(row).find('[name="editable_discount"]');
 
 654     var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
 
 655     if (price_editable == 1 && source === '') {
 
 657       $(editable_div_elt).show();
 
 658       $(not_editable_div_elt).hide();
 
 659       $(editable_div_elt).find(':input').prop("disabled", false);
 
 660       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 663       $(editable_div_elt).hide();
 
 664       $(not_editable_div_elt).show();
 
 665       $(editable_div_elt).find(':input').prop("disabled", true);
 
 666       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 670       var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
 
 671       var html_elt     = $(row).find('[name="discount_text"]');
 
 672       discount_elt.val(discount_str);
 
 673       html_elt.html(discount_str);
 
 674       ns.recalc_amounts_and_taxes();
 
 677     kivi.io.close_dialog();
 
 680   ns.show_periodic_invoices_config_dialog = function() {
 
 681     if ($('#type').val() !== 'sales_order') return;
 
 684       url:    'controller.pl?action=Order/show_periodic_invoices_config_dialog',
 
 685       data:   { type:              $('#type').val(),
 
 687                 config:            $('#order_periodic_invoices_config').val(),
 
 688                 customer_id:       $('#order_customer_id').val(),
 
 689                 transdate_as_date: $('#order_transdate_as_date').val(),
 
 690                 language_id:       $('#language_id').val()
 
 692       id:     'jq_periodic_invoices_config_dialog',
 
 693       load:   kivi.reinit_widgets,
 
 695         title:  kivi.t8('Edit the configuration for periodic invoices'),
 
 703   ns.close_periodic_invoices_config_dialog = function() {
 
 704     $('#jq_periodic_invoices_config_dialog').dialog('close');
 
 707   ns.assign_periodic_invoices_config = function() {
 
 708     var data = $('[name="Form"]').serializeArray();
 
 709     data.push({ name: 'type',   value: $('#type').val() },
 
 710               { name: 'action', value: 'Order/assign_periodic_invoices_config' });
 
 711     $.post("controller.pl", data, kivi.eval_json_result);
 
 714   ns.check_save_active_periodic_invoices = function() {
 
 715     var type = $('#type').val();
 
 716     if (type !== 'sales_order') return true;
 
 720       url:      'controller.pl',
 
 721       data:     { action: 'Order/get_has_active_periodic_invoices',
 
 724                   config: $('#order_periodic_invoices_config').val(),
 
 729       success:  function(val) {
 
 735       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?'));
 
 741   ns.show_vc_details_dialog = function() {
 
 742     if (!ns.check_cv()) return;
 
 746     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 748       vc_id = $('#order_customer_id').val();
 
 749       title = kivi.t8('Customer details');
 
 752       vc_id = $('#order_vendor_id').val();
 
 753       title = kivi.t8('Vendor details');
 
 757       url:    'controller.pl',
 
 758       data:   { action: 'Order/show_customer_vendor_details_dialog',
 
 759                 type  : $('#type').val(),
 
 763       id:     'jq_customer_vendor_details_dialog',
 
 773   ns.update_row_from_master_data = function(clicked) {
 
 774     var row = $(clicked).parents("tbody").first();
 
 775     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 777     var data = $('#order_form').serializeArray();
 
 778     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
 
 779     data.push({ name: 'item_ids[]', value: item_id_dom.val() });
 
 781     $.post("controller.pl", data, kivi.eval_json_result);
 
 784   ns.update_all_rows_from_master_data = function() {
 
 785     var item_ids = $.map($('.row_entry'), function(elt) {
 
 786       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
 
 787       return { name: 'item_ids[]', value: item_id };
 
 790     if (item_ids.length == 0) {
 
 794     var data = $('#order_form').serializeArray();
 
 795     data.push({ name: 'action', value: 'Order/update_row_from_master_data' });
 
 796     data = data.concat(item_ids);
 
 798     $.post("controller.pl", data, kivi.eval_json_result);
 
 801   ns.show_calculate_qty_dialog = function(clicked) {
 
 802     var row        = $(clicked).parents("tbody").first();
 
 803     var input_id   = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
 
 804     var formula_id = $(row).find('[name="formula[+]"]').attr('id');
 
 806     calculate_qty_selection_dialog("", input_id, "", formula_id);
 
 810   ns.edit_custom_shipto = function() {
 
 811     if (!ns.check_cv()) return;
 
 813     kivi.SalesPurchase.edit_custom_shipto();
 
 816   ns.purchase_order_check_for_direct_delivery = function() {
 
 817     if ($('#type').val() != 'sales_order') {
 
 818       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 823     if ($('#order_shipto_id').val() !== '') {
 
 825       shipto = $('#order_shipto_id option:selected').text();
 
 827       $('#shipto_inputs [id^="shipto"]').each(function(idx, elt) {
 
 828         if (!empty)                                     return true;
 
 829         if (/^shipto_to_copy/.test($(elt).prop('id')))  return true;
 
 830         if (/^shiptocp_gender/.test($(elt).prop('id'))) return true;
 
 831         if (/^shiptocvar_/.test($(elt).prop('id')))     return true;
 
 832         if ($(elt).val() !== '') {
 
 837       var shipto_elements = [];
 
 838       $([$('#shiptoname').val(), $('#shiptostreet').val(), $('#shiptozipcode').val(), $('#shiptocity').val()]).each(function(idx, elt) {
 
 839         if (elt !== '') shipto_elements.push(elt);
 
 841       shipto = shipto_elements.join('; ');
 
 846       ns.direct_delivery_dialog(shipto);
 
 848       kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 852   ns.direct_delivery_callback = function(accepted) {
 
 853     $('#direct-delivery-dialog').dialog('close');
 
 856       $('<input type="hidden" name="use_shipto">').appendTo('#order_form').val('1');
 
 859     kivi.submit_form_with_action($('#order_form'), 'Order/purchase_order');
 
 862   ns.direct_delivery_dialog = function(shipto) {
 
 863     $('#direct-delivery-dialog').remove();
 
 865     var text1 = kivi.t8('You have entered or selected the following shipping address for this customer:');
 
 866     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?');
 
 867     var html  = '<div id="direct-delivery-dialog"><p>' + text1 + '</p><p>' + shipto + '</p><p>' + text2 + '</p>';
 
 868     html      = html + '<hr><p>';
 
 869     html      = html + '<input type="button" value="' + kivi.t8('Yes') + '" size="30" onclick="kivi.Order.direct_delivery_callback(true)">';
 
 870     html      = html + ' ';
 
 871     html      = html + '<input type="button" value="' + kivi.t8('No')  + '" size="30" onclick="kivi.Order.direct_delivery_callback(false)">';
 
 872     html      = html + '</p></div>';
 
 873     $(html).hide().appendTo('#order_form');
 
 875     kivi.popup_dialog({id: 'direct-delivery-dialog',
 
 876                        dialog: {title:  kivi.t8('Carry over shipping address'),
 
 881   ns.follow_up_window = function() {
 
 882     var id   = $('#id').val();
 
 883     var type = $('#type').val();
 
 885     var number_info = '';
 
 886     if ($('#type').val() == 'sales_order' || $('#type').val() == 'purchase_order') {
 
 887       number_info = $('#order_ordnumber').val();
 
 888     } else if ($('#type').val() == 'sales_quotation' || $('#type').val() == 'request_quotation') {
 
 889       number_info = $('#order_quonumber').val();
 
 893     if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation') {
 
 894       name_info = $('#order_customer_id_name').val();
 
 895     } else if ($('#type').val() == 'purchase_order' || $('#type').val() == 'request_quotation') {
 
 896       name_info = $('#order_vendor_id_name').val();
 
 900     if (number_info !== '') { info += ' (' + number_info + ')' }
 
 901     if (name_info   !== '') { info += ' (' + name_info + ')' }
 
 903     if (!$('#follow_up_rowcount').lenght) {
 
 904       $('<input type="hidden" name="follow_up_rowcount"        id="follow_up_rowcount">').appendTo('#order_form');
 
 905       $('<input type="hidden" name="follow_up_trans_id_1"      id="follow_up_trans_id_1">').appendTo('#order_form');
 
 906       $('<input type="hidden" name="follow_up_trans_type_1"    id="follow_up_trans_type_1">').appendTo('#order_form');
 
 907       $('<input type="hidden" name="follow_up_trans_info_1"    id="follow_up_trans_info_1">').appendTo('#order_form');
 
 908       $('<input type="hidden" name="follow_up_trans_subject_1" id="follow_up_trans_subject_1">').appendTo('#order_form');
 
 910     $('#follow_up_rowcount').val(1);
 
 911     $('#follow_up_trans_id_1').val(id);
 
 912     $('#follow_up_trans_type_1').val(type);
 
 913     $('#follow_up_trans_info_1').val(info);
 
 914     $('#follow_up_trans_subject_1').val($('#order_transaction_description').val());
 
 922   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 923     $('#order_customer_id').change(kivi.Order.reload_cv_dependent_selections);
 
 925     $('#order_vendor_id').change(kivi.Order.reload_cv_dependent_selections);
 
 928   $('#order_currency_id').change(kivi.Order.update_exchangerate);
 
 929   $('#order_transdate_as_date').change(kivi.Order.update_exchangerate);
 
 930   $('#order_exchangerate_as_null_number').change(kivi.Order.exchangerate_changed);
 
 932   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 933     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
 
 935     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
 
 937   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
 
 938   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
 
 940   $('.add_item_input').keydown(function(event) {
 
 941     if (event.keyCode == 13) {
 
 942       event.preventDefault();
 
 943       kivi.Order.add_item();
 
 948   kivi.Order.init_row_handlers();
 
 950   $('#row_table_id').on('sortstop', function(event, ui) {
 
 951     $('#row_table_id thead a img').remove();
 
 952     kivi.Order.renumber_positions();
 
 955   $('#expand_all').on('click', function(event) {
 
 956     event.preventDefault();
 
 957     if ($('#expand_all').data('expanded') == 1) {
 
 958       $('#expand_all').data('expanded', 0);
 
 959       $('#expand_all').attr('src', 'image/expand.svg');
 
 960       $('#expand_all').attr('alt', kivi.t8('Show all details'));
 
 961       $('#expand_all').attr('title', kivi.t8('Show all details'));
 
 962       $('.row_entry').each(function(idx, elt) {
 
 963         kivi.Order.hide_second_row(elt);
 
 966       $('#expand_all').data('expanded', 1);
 
 967       $('#expand_all').attr('src', "image/collapse.svg");
 
 968       $('#expand_all').attr('alt', kivi.t8('Hide all details'));
 
 969       $('#expand_all').attr('title', kivi.t8('Hide all details'));
 
 970       kivi.Order.load_all_second_rows();
 
 971       $('.row_entry').each(function(idx, elt) {
 
 972         kivi.Order.show_second_row(elt);
 
 978   $('.reformat_number_as_null_number').change(kivi.Order.reformat_number_as_null_number);