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_save_duplicate_parts = function() {
 
  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       return confirm(kivi.t8("There are duplicate parts at positions") + "\n"
 
  32                      + pos.join(', ') + "\n"
 
  33                      + kivi.t8("Do you really want to save?"));
 
  38   ns.save = function(action, warn_on_duplicates) {
 
  39     if (!ns.check_cv()) return;
 
  40     if (warn_on_duplicates && !ns.check_save_duplicate_parts()) return;
 
  42     var data = $('#order_form').serializeArray();
 
  43     data.push({ name: 'action', value: 'Order/' + action });
 
  45     $.post("controller.pl", data, kivi.eval_json_result);
 
  48   ns.delete_order = function() {
 
  49     var data = $('#order_form').serializeArray();
 
  50     data.push({ name: 'action', value: 'Order/delete' });
 
  52     $.post("controller.pl", data, kivi.eval_json_result);
 
  55   ns.show_print_options = function() {
 
  56     if (!ns.check_cv()) return;
 
  61         title: kivi.t8('Print options'),
 
  68   ns.print = function() {
 
  69     $('#print_options').dialog('close');
 
  71     var data = $('#order_form').serializeArray();
 
  72     data = data.concat($('#print_options_form').serializeArray());
 
  73     data.push({ name: 'action', value: 'Order/print' });
 
  75     $.post("controller.pl", data, kivi.eval_json_result);
 
  78   ns.download_pdf = function(pdf_filename, key) {
 
  80     data.push({ name: 'action', value: 'Order/download_pdf' });
 
  81     data.push({ name: 'type', value: $('#type').val() });
 
  82     data.push({ name: 'pdf_filename', value: pdf_filename });
 
  83     data.push({ name: 'key', value: key });
 
  84     $.download("controller.pl", data);
 
  87   ns.email = function() {
 
  88     if (!ns.check_cv()) return;
 
  89     var data = $('#order_form').serializeArray();
 
  90     data.push({ name: 'action', value: 'Order/show_email_dialog' });
 
  92     $.post("controller.pl", data, kivi.eval_json_result);
 
  97   ns.setup_send_email_dialog = function() {
 
  98     kivi.SalesPurchase.show_all_print_options_elements();
 
  99     kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false);
 
 101     $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
 
 103     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
 
 104     $('#email_form_' + to_focus).focus();
 
 107   ns.finish_send_email_dialog = function() {
 
 108     kivi.SalesPurchase.show_all_print_options_elements();
 
 110     $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
 
 114   ns.show_email_dialog = function(html) {
 
 115     var id            = 'send_email_dialog';
 
 116     var dialog_params = {
 
 120       title:  kivi.t8('Send email'),
 
 122       beforeClose: kivi.Order.finish_send_email_dialog,
 
 123       close: function(event, ui) {
 
 124         email_dialog.remove();
 
 128     $('#' + id).remove();
 
 130     email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
 
 131     email_dialog.html(html);
 
 132     email_dialog.dialog(dialog_params);
 
 134     kivi.Order.setup_send_email_dialog();
 
 136     $('.cancel').click(ns.close_email_dialog);
 
 141   ns.send_email = function() {
 
 142     var data = $('#order_form').serializeArray();
 
 143     data = data.concat($('[name^="email_form."]').serializeArray());
 
 144     data = data.concat($('[name^="print_options."]').serializeArray());
 
 145     data.push({ name: 'action', value: 'Order/send_email' });
 
 146     $.post("controller.pl", data, kivi.eval_json_result);
 
 149   ns.close_email_dialog = function() {
 
 150     email_dialog.dialog("close");
 
 153   ns.set_number_in_title = function(elt) {
 
 154     $('#nr_in_title').html($(elt).val());
 
 157   ns.reload_cv_dependant_selections = function() {
 
 158     var data = $('#order_form').serializeArray();
 
 159     data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
 
 161     $.post("controller.pl", data, kivi.eval_json_result);
 
 164   ns.reformat_number = function(event) {
 
 165     $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
 
 168   ns.recalc_amounts_and_taxes = function() {
 
 169     var data = $('#order_form').serializeArray();
 
 170     data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
 
 172     $.post("controller.pl", data, kivi.eval_json_result);
 
 175   ns.unit_change = function(event) {
 
 176     var row = $(event.target).parents("tbody").first();
 
 177     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 178     var sellprice_dom = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 179     var select_elt = $(row).find('[name="order.orderitems[].unit"]');
 
 181     var oldval = $(select_elt).data('oldval');
 
 182     $(select_elt).data('oldval', $(select_elt).val());
 
 184     var data = $('#order_form').serializeArray();
 
 185     data.push({ name: 'action', value: 'Order/unit_changed' });
 
 186     data.push({ name: 'item_id', value: item_id_dom.val() });
 
 187     data.push({ name: 'old_unit', value: oldval });
 
 188     data.push({ name: 'sellprice_dom_id', value: sellprice_dom.attr('id') });
 
 190     $.post("controller.pl", data, kivi.eval_json_result);
 
 193   ns.update_sellprice = function(item_id, price_str) {
 
 194     var row = $('#item_' + item_id).parents("tbody").first();
 
 195     var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 196     var html_elt  = $(row).find('[name="sellprice_text"]');
 
 197     price_elt.val(price_str);
 
 198     html_elt.html(price_str);
 
 201   ns.load_second_row = function(row) {
 
 202     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 203     var div_elt = $(row).find('[name="second_row"]');
 
 205     if ($(div_elt).data('loaded') == 1) {
 
 208     var data = $('#order_form').serializeArray();
 
 209     data.push({ name: 'action', value: 'Order/load_second_rows' });
 
 210     data.push({ name: 'item_ids[]', value: item_id_dom.val() });
 
 212     $.post("controller.pl", data, kivi.eval_json_result);
 
 215   ns.load_all_second_rows = function() {
 
 216     var rows = $('.row_entry').filter(function(idx, elt) {
 
 217       return $(elt).find('[name="second_row"]').data('loaded') != 1;
 
 220     var item_ids = $.map(rows, function(elt) {
 
 221       var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
 
 222       return { name: 'item_ids[]', value: item_id };
 
 225     if (item_ids.length == 0) {
 
 229     var data = $('#order_form').serializeArray();
 
 230     data.push({ name: 'action', value: 'Order/load_second_rows' });
 
 231     data = data.concat(item_ids);
 
 233     $.post("controller.pl", data, kivi.eval_json_result);
 
 236   ns.hide_second_row = function(row) {
 
 237     $(row).children().not(':first').hide();
 
 238     $(row).data('expanded', 0);
 
 239     var elt = $(row).find('.expand');
 
 240     elt.attr('src', "image/expand.svg");
 
 241     elt.attr('alt', kivi.t8('Show details'));
 
 242     elt.attr('title', kivi.t8('Show details'));
 
 245   ns.show_second_row = function(row) {
 
 246     $(row).children().not(':first').show();
 
 247     $(row).data('expanded', 1);
 
 248     var elt = $(row).find('.expand');
 
 249     elt.attr('src', "image/collapse.svg");
 
 250     elt.attr('alt', kivi.t8('Hide details'));
 
 251     elt.attr('title', kivi.t8('Hide details'));
 
 254   ns.toggle_second_row = function(row) {
 
 255     if ($(row).data('expanded') == 1) {
 
 256       ns.hide_second_row(row);
 
 258       ns.show_second_row(row);
 
 262   ns.init_row_handlers = function() {
 
 263     kivi.run_once_for('.recalc', 'on_change_recalc', function(elt) {
 
 264       $(elt).change(ns.recalc_amounts_and_taxes);
 
 267     kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
 
 268       $(elt).change(ns.reformat_number);
 
 271     kivi.run_once_for('.unitselect', 'on_change_unit_with_oldval', function(elt) {
 
 272       $(elt).data('oldval', $(elt).val());
 
 273       $(elt).change(ns.unit_change);
 
 276     kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
 
 277       $(elt).keydown(function(event) {
 
 278         if(event.keyCode == 40 && event.shiftKey === true) {
 
 280           event.preventDefault();
 
 281           var row = $(event.target).parents(".row_entry").first();
 
 282           ns.load_second_row(row);
 
 283           ns.show_second_row(row);
 
 286         if(event.keyCode == 38 && event.shiftKey === true) {
 
 288           event.preventDefault();
 
 289           var row = $(event.target).parents(".row_entry").first();
 
 290           ns.hide_second_row(row);
 
 296     kivi.run_once_for('.expand', 'expand_second_row', function(elt) {
 
 297       $(elt).click(function(event) {
 
 298         event.preventDefault();
 
 299         var row = $(event.target).parents(".row_entry").first();
 
 300         ns.load_second_row(row);
 
 301         ns.toggle_second_row(row);
 
 308   ns.redisplay_line_values = function(is_sales, data) {
 
 309     $('.row_entry').each(function(idx, elt) {
 
 310       $(elt).find('[name="linetotal"]').html(data[idx][0]);
 
 311       if (is_sales && $(elt).find('[name="second_row"]').data('loaded') == 1) {
 
 312         var mt = data[idx][1];
 
 313         var mp = data[idx][2];
 
 315         if (mt[0] === '-') h += ' class="plus0"';
 
 316         h += '>' + mt + '  ' + mp + '%';
 
 318         $(elt).find('[name="linemargin"]').html(h);
 
 323   ns.renumber_positions = function() {
 
 324     $('.row_entry [name="position"]').each(function(idx, elt) {
 
 329   ns.reorder_items = function(order_by) {
 
 330     var dir = $('#' + order_by + '_header_id a img').attr("data-sort-dir");
 
 331     $('#row_table_id thead a img').remove();
 
 336       src = "image/up.png";
 
 339       src = "image/down.png";
 
 342     $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
 
 344     var data = $('#order_form').serializeArray();
 
 345     data.push({ name: 'action', value: 'Order/reorder_items' });
 
 346     data.push({ name: 'order_by', value: order_by });
 
 347     data.push({ name: 'sort_dir', value: dir });
 
 349     $.post("controller.pl", data, kivi.eval_json_result);
 
 352   ns.redisplay_items = function(data) {
 
 353     var old_rows = $('.row_entry').detach();
 
 355     $(data).each(function(idx, elt) {
 
 356       new_rows.push(old_rows[elt.old_pos - 1]);
 
 358     $(new_rows).appendTo($('#row_table_id'));
 
 359     ns.renumber_positions();
 
 362   ns.add_item = function() {
 
 363     if ($('#add_item_parts_id').val() === '') return;
 
 364     if (!ns.check_cv()) return;
 
 366     $('#row_table_id thead a img').remove();
 
 368     var data = $('#order_form').serializeArray();
 
 369     data.push({ name: 'action', value: 'Order/add_item' });
 
 371     $.post("controller.pl", data, kivi.eval_json_result);
 
 374   ns.show_multi_items_dialog = function() {
 
 375     if (!ns.check_cv()) return;
 
 377     $('#row_table_id thead a img').remove();
 
 380       url: 'controller.pl?action=Order/show_multi_items_dialog',
 
 381       data: { type: $('#type').val(),
 
 382               callback: 'Order/add_multi_items',
 
 383               callback_data_id: 'order_form' },
 
 384       id: 'jq_multi_items_dialog',
 
 386         title: kivi.t8('Add multiple items'),
 
 394   ns.close_multi_items_dialog = function() {
 
 395     $('#jq_multi_items_dialog').dialog('close');
 
 398   ns.delete_order_item_row = function(clicked) {
 
 399     var row = $(clicked).parents("tbody").first();
 
 402     ns.renumber_positions();
 
 403     ns.recalc_amounts_and_taxes();
 
 406   ns.row_table_scroll_down = function() {
 
 407     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
 
 410   ns.show_longdescription_dialog = function(clicked) {
 
 411     var row = $(clicked).parents("tbody").first();
 
 412     var position = $(row).find('[name="position"]').html();
 
 413     var partnumber = $(row).find('[name="partnumber"]').html();
 
 414     var description_elt = $(row).find('[name="order.orderitems[].description"]');
 
 415     var description = description_elt.val();
 
 416     var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
 
 419     if (!longdescription_elt.length) {
 
 421       data.push({ name: 'action', value: 'Order/get_item_longdescription' });
 
 422       data.push({ name: 'type', value: $('#type').val() });
 
 423       data.push({ name: 'item_id', value: $(row).find('[name="order.orderitems[+].id"]').val() });
 
 424       data.push({ name: 'parts_id', value: $(row).find('[name="order.orderitems[].parts_id"]').val() });
 
 426         url: 'controller.pl',
 
 431         success: function(val){
 
 432           longdescription = val;
 
 436       longdescription = longdescription_elt.val();
 
 439     var params = { runningnumber: position,
 
 440                    partnumber: partnumber,
 
 441                    description: description,
 
 442                    default_longdescription: longdescription,
 
 443                    set_function: function(val){
 
 444                      longdescription_elt.remove();
 
 445                      $('<input type="hidden" name="order.orderitems[].longdescription">').insertAfter(description_elt).val(val);
 
 449     kivi.SalesPurchase.edit_longdescription_with_params(params);
 
 452   ns.price_chooser_item_row = function(clicked) {
 
 453     var row = $(clicked).parents("tbody").first();
 
 454     var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
 
 456     var data = $('#order_form').serializeArray();
 
 457     data.push({ name: 'action', value: 'Order/price_popup' });
 
 458     data.push({ name: 'item_id', value: item_id_dom.val() });
 
 460     $.post("controller.pl", data, kivi.eval_json_result);
 
 463   ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
 
 464     var row = $('#item_' + item_id).parents("tbody").first();
 
 465     var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
 
 466     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 468     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
 
 469     source_elt.val(source);
 
 471     var editable_div_elt = $(row).find('[name="editable_price"]');
 
 472     var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
 
 473     if (price_editable == 1 && source === '') {
 
 475       $(editable_div_elt).show();
 
 476       $(not_editable_div_elt).hide();
 
 477       $(editable_div_elt).find(':input').prop("disabled", false);
 
 478       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 481       $(editable_div_elt).hide();
 
 482       $(not_editable_div_elt).show();
 
 483       $(editable_div_elt).find(':input').prop("disabled", true);
 
 484       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 488       var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
 
 489       var html_elt  = $(row).find('[name="sellprice_text"]');
 
 490       price_elt.val(price_str);
 
 491       html_elt.html(price_str);
 
 492       ns.recalc_amounts_and_taxes();
 
 495     kivi.io.close_dialog();
 
 498   ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
 
 499     var row = $('#item_' + item_id).parents("tbody").first();
 
 500     var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
 
 501     var button_elt = $(row).find('[name="price_chooser_button"]');
 
 503     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
 
 504     source_elt.val(source);
 
 506     var editable_div_elt = $(row).find('[name="editable_discount"]');
 
 507     var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
 
 508     if (price_editable == 1 && source === '') {
 
 510       $(editable_div_elt).show();
 
 511       $(not_editable_div_elt).hide();
 
 512       $(editable_div_elt).find(':input').prop("disabled", false);
 
 513       $(not_editable_div_elt).find(':input').prop("disabled", true);
 
 516       $(editable_div_elt).hide();
 
 517       $(not_editable_div_elt).show();
 
 518       $(editable_div_elt).find(':input').prop("disabled", true);
 
 519       $(not_editable_div_elt).find(':input').prop("disabled", false);
 
 523       var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
 
 524       var html_elt     = $(row).find('[name="discount_text"]');
 
 525       discount_elt.val(discount_str);
 
 526       html_elt.html(discount_str);
 
 527       ns.recalc_amounts_and_taxes();
 
 530     kivi.io.close_dialog();
 
 533   ns.show_periodic_invoices_config_dialog = function() {
 
 534     if ($('#type').val() !== 'sales_order') return;
 
 537       url: 'controller.pl?action=Order/show_periodic_invoices_config_dialog',
 
 538       data: { type       : $('#type').val(),
 
 540               config     : $('#order_periodic_invoices_config').val(),
 
 541               customer_id: $('#order_customer_id').val(),
 
 542               transdate  : $('#order_transdate').val(),
 
 543               language_id: $('#language_id').val()
 
 545       id: 'jq_periodic_invoices_config_dialog',
 
 546       load: kivi.reinit_widgets,
 
 548         title: kivi.t8('Edit the configuration for periodic invoices'),
 
 556   ns.close_periodic_invoices_config_dialog = function() {
 
 557     $('#jq_periodic_invoices_config_dialog').dialog('close');
 
 560   ns.assign_periodic_invoices_config = function() {
 
 561     var data = $('[name="Form"]').serializeArray();
 
 562     data.push({ name: 'type',   value: $('#type').val() });
 
 563     data.push({ name: 'action', value: 'Order/assign_periodic_invoices_config' });
 
 564     $.post("controller.pl", data, kivi.eval_json_result);
 
 567   ns.check_save_active_periodic_invoices = function() {
 
 568     var type = $('#type').val();
 
 569     if (type !== 'sales_order') return true;
 
 573       url: 'controller.pl',
 
 574       data: { action: 'Order/get_has_active_periodic_invoices',
 
 577               config: $('#order_periodic_invoices_config').val(),
 
 582       success: function(val){
 
 588       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?'));
 
 597   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 598     $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
 
 600     $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
 
 603   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
 
 604     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
 
 606     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
 
 608   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
 
 609   $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
 
 611   $('.add_item_input').keydown(function(event) {
 
 612     if(event.keyCode == 13) {
 
 613       event.preventDefault();
 
 614       kivi.Order.add_item();
 
 619   kivi.Order.init_row_handlers();
 
 621   $('#row_table_id').on('sortstop', function(event, ui) {
 
 622     $('#row_table_id thead a img').remove();
 
 623     kivi.Order.renumber_positions();
 
 626   $('#expand_all').on('click', function(event) {
 
 627     event.preventDefault();
 
 628     if ($('#expand_all').data('expanded') == 1) {
 
 629       $('#expand_all').data('expanded', 0);
 
 630       $('#expand_all').attr('src', 'image/expand.svg');
 
 631       $('#expand_all').attr('alt', kivi.t8('Show all details'));
 
 632       $('#expand_all').attr('title', kivi.t8('Show all details'));
 
 633       $('.row_entry').each(function(idx, elt) {
 
 634         kivi.Order.hide_second_row(elt);
 
 637       $('#expand_all').data('expanded', 1);
 
 638       $('#expand_all').attr('src', "image/collapse.svg");
 
 639       $('#expand_all').attr('alt', kivi.t8('Hide all details'));
 
 640       $('#expand_all').attr('title', kivi.t8('Hide all details'));
 
 641       kivi.Order.load_all_second_rows();
 
 642       $('.row_entry').each(function(idx, elt) {
 
 643         kivi.Order.show_second_row(elt);