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