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.check_valid_reqdate = function() {
39 if ($('#order_reqdate').val() === '') {
40 alert(kivi.t8('Please select a delivery date.'));
47 ns.save = function(action, warn_on_duplicates, warn_on_reqdate) {
48 if (!ns.check_cv()) return;
49 if (warn_on_duplicates && !ns.check_save_duplicate_parts()) return;
50 if (warn_on_reqdate && !ns.check_valid_reqdate()) return;
52 var data = $('#order_form').serializeArray();
53 data.push({ name: 'action', value: 'Order/' + action });
55 $.post("controller.pl", data, kivi.eval_json_result);
58 ns.delete_order = function() {
59 var data = $('#order_form').serializeArray();
60 data.push({ name: 'action', value: 'Order/delete' });
62 $.post("controller.pl", data, kivi.eval_json_result);
65 ns.show_print_options = function() {
66 if (!ns.check_cv()) return;
71 title: kivi.t8('Print options'),
78 ns.print = function() {
79 $('#print_options').dialog('close');
81 var data = $('#order_form').serializeArray();
82 data = data.concat($('#print_options_form').serializeArray());
83 data.push({ name: 'action', value: 'Order/print' });
85 $.post("controller.pl", data, kivi.eval_json_result);
88 ns.download_pdf = function(pdf_filename, key) {
89 var data = [{ name: 'action', value: 'Order/download_pdf' },
90 { name: 'type', value: $('#type').val() },
91 { name: 'pdf_filename', value: pdf_filename },
92 { name: 'key', value: key }];
93 $.download("controller.pl", data);
96 ns.email = function() {
97 if (!ns.check_cv()) return;
98 var data = $('#order_form').serializeArray();
99 data.push({ name: 'action', value: 'Order/show_email_dialog' });
101 $.post("controller.pl", data, kivi.eval_json_result);
106 ns.setup_send_email_dialog = function() {
107 kivi.SalesPurchase.show_all_print_options_elements();
108 kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false);
110 $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
112 var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
113 $('#email_form_' + to_focus).focus();
116 ns.finish_send_email_dialog = function() {
117 kivi.SalesPurchase.show_all_print_options_elements();
119 $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
123 ns.show_email_dialog = function(html) {
124 var id = 'send_email_dialog';
125 var dialog_params = {
129 title: kivi.t8('Send email'),
131 beforeClose: kivi.Order.finish_send_email_dialog,
132 close: function(event, ui) {
133 email_dialog.remove();
137 $('#' + id).remove();
139 email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
140 email_dialog.html(html);
141 email_dialog.dialog(dialog_params);
143 kivi.Order.setup_send_email_dialog();
145 $('.cancel').click(ns.close_email_dialog);
150 ns.send_email = function() {
151 var data = $('#order_form').serializeArray();
152 data = data.concat($('[name^="email_form."]').serializeArray());
153 data = data.concat($('[name^="print_options."]').serializeArray());
154 data.push({ name: 'action', value: 'Order/send_email' });
155 $.post("controller.pl", data, kivi.eval_json_result);
158 ns.close_email_dialog = function() {
159 email_dialog.dialog("close");
162 ns.set_number_in_title = function(elt) {
163 $('#nr_in_title').html($(elt).val());
166 ns.reload_cv_dependant_selections = function() {
167 var data = $('#order_form').serializeArray();
168 data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
170 $.post("controller.pl", data, kivi.eval_json_result);
173 ns.reformat_number = function(event) {
174 $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
177 ns.recalc_amounts_and_taxes = function() {
178 var data = $('#order_form').serializeArray();
179 data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
181 $.post("controller.pl", data, kivi.eval_json_result);
184 ns.unit_change = function(event) {
185 var row = $(event.target).parents("tbody").first();
186 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
187 var sellprice_dom = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
188 var select_elt = $(row).find('[name="order.orderitems[].unit"]');
190 var oldval = $(select_elt).data('oldval');
191 $(select_elt).data('oldval', $(select_elt).val());
193 var data = $('#order_form').serializeArray();
194 data.push({ name: 'action', value: 'Order/unit_changed' },
195 { name: 'item_id', value: item_id_dom.val() },
196 { name: 'old_unit', value: oldval },
197 { name: 'sellprice_dom_id', value: sellprice_dom.attr('id') });
199 $.post("controller.pl", data, kivi.eval_json_result);
202 ns.update_sellprice = function(item_id, price_str) {
203 var row = $('#item_' + item_id).parents("tbody").first();
204 var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
205 var html_elt = $(row).find('[name="sellprice_text"]');
206 price_elt.val(price_str);
207 html_elt.html(price_str);
210 ns.load_second_row = function(row) {
211 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
212 var div_elt = $(row).find('[name="second_row"]');
214 if ($(div_elt).data('loaded') == 1) {
217 var data = $('#order_form').serializeArray();
218 data.push({ name: 'action', value: 'Order/load_second_rows' },
219 { name: 'item_ids[]', value: item_id_dom.val() });
221 $.post("controller.pl", data, kivi.eval_json_result);
224 ns.load_all_second_rows = function() {
225 var rows = $('.row_entry').filter(function(idx, elt) {
226 return $(elt).find('[name="second_row"]').data('loaded') != 1;
229 var item_ids = $.map(rows, function(elt) {
230 var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
231 return { name: 'item_ids[]', value: item_id };
234 if (item_ids.length == 0) {
238 var data = $('#order_form').serializeArray();
239 data.push({ name: 'action', value: 'Order/load_second_rows' });
240 data = data.concat(item_ids);
242 $.post("controller.pl", data, kivi.eval_json_result);
245 ns.hide_second_row = function(row) {
246 $(row).children().not(':first').hide();
247 $(row).data('expanded', 0);
248 var elt = $(row).find('.expand');
249 elt.attr('src', "image/expand.svg");
250 elt.attr('alt', kivi.t8('Show details'));
251 elt.attr('title', kivi.t8('Show details'));
254 ns.show_second_row = function(row) {
255 $(row).children().not(':first').show();
256 $(row).data('expanded', 1);
257 var elt = $(row).find('.expand');
258 elt.attr('src', "image/collapse.svg");
259 elt.attr('alt', kivi.t8('Hide details'));
260 elt.attr('title', kivi.t8('Hide details'));
263 ns.toggle_second_row = function(row) {
264 if ($(row).data('expanded') == 1) {
265 ns.hide_second_row(row);
267 ns.show_second_row(row);
271 ns.init_row_handlers = function() {
272 kivi.run_once_for('.recalc', 'on_change_recalc', function(elt) {
273 $(elt).change(ns.recalc_amounts_and_taxes);
276 kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
277 $(elt).change(ns.reformat_number);
280 kivi.run_once_for('.unitselect', 'on_change_unit_with_oldval', function(elt) {
281 $(elt).data('oldval', $(elt).val());
282 $(elt).change(ns.unit_change);
285 kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
286 $(elt).keydown(function(event) {
287 if (event.keyCode == 40 && event.shiftKey === true) {
289 event.preventDefault();
290 var row = $(event.target).parents(".row_entry").first();
291 ns.load_second_row(row);
292 ns.show_second_row(row);
295 if (event.keyCode == 38 && event.shiftKey === true) {
297 event.preventDefault();
298 var row = $(event.target).parents(".row_entry").first();
299 ns.hide_second_row(row);
305 kivi.run_once_for('.expand', 'expand_second_row', function(elt) {
306 $(elt).click(function(event) {
307 event.preventDefault();
308 var row = $(event.target).parents(".row_entry").first();
309 ns.load_second_row(row);
310 ns.toggle_second_row(row);
317 ns.redisplay_line_values = function(is_sales, data) {
318 $('.row_entry').each(function(idx, elt) {
319 $(elt).find('[name="linetotal"]').html(data[idx][0]);
320 if (is_sales && $(elt).find('[name="second_row"]').data('loaded') == 1) {
321 var mt = data[idx][1];
322 var mp = data[idx][2];
324 if (mt[0] === '-') h += ' class="plus0"';
325 h += '>' + mt + ' ' + mp + '%';
327 $(elt).find('[name="linemargin"]').html(h);
332 ns.renumber_positions = function() {
333 $('.row_entry [name="position"]').each(function(idx, elt) {
338 ns.reorder_items = function(order_by) {
339 var dir = $('#' + order_by + '_header_id a img').attr("data-sort-dir");
340 $('#row_table_id thead a img').remove();
345 src = "image/up.png";
348 src = "image/down.png";
351 $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
353 var data = $('#order_form').serializeArray();
354 data.push({ name: 'action', value: 'Order/reorder_items' },
355 { name: 'order_by', value: order_by },
356 { name: 'sort_dir', value: dir });
358 $.post("controller.pl", data, kivi.eval_json_result);
361 ns.redisplay_items = function(data) {
362 var old_rows = $('.row_entry').detach();
364 $(data).each(function(idx, elt) {
365 new_rows.push(old_rows[elt.old_pos - 1]);
367 $(new_rows).appendTo($('#row_table_id'));
368 ns.renumber_positions();
371 ns.add_item = function() {
372 if ($('#add_item_parts_id').val() === '') return;
373 if (!ns.check_cv()) return;
375 $('#row_table_id thead a img').remove();
377 var data = $('#order_form').serializeArray();
378 data.push({ name: 'action', value: 'Order/add_item' });
380 $.post("controller.pl", data, kivi.eval_json_result);
383 ns.show_multi_items_dialog = function() {
384 if (!ns.check_cv()) return;
386 $('#row_table_id thead a img').remove();
389 url: 'controller.pl?action=Order/show_multi_items_dialog',
390 data: { type: $('#type').val(),
391 callback: 'Order/add_multi_items',
392 callback_data_id: 'order_form' },
393 id: 'jq_multi_items_dialog',
395 title: kivi.t8('Add multiple items'),
403 ns.close_multi_items_dialog = function() {
404 $('#jq_multi_items_dialog').dialog('close');
407 ns.delete_order_item_row = function(clicked) {
408 var row = $(clicked).parents("tbody").first();
411 ns.renumber_positions();
412 ns.recalc_amounts_and_taxes();
415 ns.row_table_scroll_down = function() {
416 $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
419 ns.show_longdescription_dialog = function(clicked) {
420 var row = $(clicked).parents("tbody").first();
421 var position = $(row).find('[name="position"]').html();
422 var partnumber = $(row).find('[name="partnumber"]').html();
423 var description_elt = $(row).find('[name="order.orderitems[].description"]');
424 var description = description_elt.val();
425 var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
428 if (!longdescription_elt.length) {
430 { name: 'action', value: 'Order/get_item_longdescription' },
431 { name: 'type', value: $('#type').val() },
432 { name: 'item_id', value: $(row).find('[name="order.orderitems[+].id"]').val() },
433 { name: 'parts_id', value: $(row).find('[name="order.orderitems[].parts_id"]').val() }
437 url: 'controller.pl',
442 success: function(val) {
443 longdescription = val;
447 longdescription = longdescription_elt.val();
451 runningnumber: position,
452 partnumber: partnumber,
453 description: description,
454 default_longdescription: longdescription,
455 set_function: function(val) {
456 longdescription_elt.remove();
457 $('<input type="hidden" name="order.orderitems[].longdescription">').insertAfter(description_elt).val(val);
461 kivi.SalesPurchase.edit_longdescription_with_params(params);
464 ns.price_chooser_item_row = function(clicked) {
465 if (!ns.check_cv()) return;
466 var row = $(clicked).parents("tbody").first();
467 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
469 var data = $('#order_form').serializeArray();
470 data.push({ name: 'action', value: 'Order/price_popup' },
471 { name: 'item_id', value: item_id_dom.val() });
473 $.post("controller.pl", data, kivi.eval_json_result);
476 ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
477 var row = $('#item_' + item_id).parents("tbody").first();
478 var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
479 var button_elt = $(row).find('[name="price_chooser_button"]');
481 button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
482 source_elt.val(source);
484 var editable_div_elt = $(row).find('[name="editable_price"]');
485 var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
486 if (price_editable == 1 && source === '') {
488 $(editable_div_elt).show();
489 $(not_editable_div_elt).hide();
490 $(editable_div_elt).find(':input').prop("disabled", false);
491 $(not_editable_div_elt).find(':input').prop("disabled", true);
494 $(editable_div_elt).hide();
495 $(not_editable_div_elt).show();
496 $(editable_div_elt).find(':input').prop("disabled", true);
497 $(not_editable_div_elt).find(':input').prop("disabled", false);
501 var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
502 var html_elt = $(row).find('[name="sellprice_text"]');
503 price_elt.val(price_str);
504 html_elt.html(price_str);
505 ns.recalc_amounts_and_taxes();
508 kivi.io.close_dialog();
511 ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
512 var row = $('#item_' + item_id).parents("tbody").first();
513 var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
514 var button_elt = $(row).find('[name="price_chooser_button"]');
516 button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
517 source_elt.val(source);
519 var editable_div_elt = $(row).find('[name="editable_discount"]');
520 var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
521 if (price_editable == 1 && source === '') {
523 $(editable_div_elt).show();
524 $(not_editable_div_elt).hide();
525 $(editable_div_elt).find(':input').prop("disabled", false);
526 $(not_editable_div_elt).find(':input').prop("disabled", true);
529 $(editable_div_elt).hide();
530 $(not_editable_div_elt).show();
531 $(editable_div_elt).find(':input').prop("disabled", true);
532 $(not_editable_div_elt).find(':input').prop("disabled", false);
536 var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
537 var html_elt = $(row).find('[name="discount_text"]');
538 discount_elt.val(discount_str);
539 html_elt.html(discount_str);
540 ns.recalc_amounts_and_taxes();
543 kivi.io.close_dialog();
546 ns.show_periodic_invoices_config_dialog = function() {
547 if ($('#type').val() !== 'sales_order') return;
550 url: 'controller.pl?action=Order/show_periodic_invoices_config_dialog',
551 data: { type: $('#type').val(),
553 config: $('#order_periodic_invoices_config').val(),
554 customer_id: $('#order_customer_id').val(),
555 transdate: $('#order_transdate').val(),
556 language_id: $('#language_id').val()
558 id: 'jq_periodic_invoices_config_dialog',
559 load: kivi.reinit_widgets,
561 title: kivi.t8('Edit the configuration for periodic invoices'),
569 ns.close_periodic_invoices_config_dialog = function() {
570 $('#jq_periodic_invoices_config_dialog').dialog('close');
573 ns.assign_periodic_invoices_config = function() {
574 var data = $('[name="Form"]').serializeArray();
575 data.push({ name: 'type', value: $('#type').val() },
576 { name: 'action', value: 'Order/assign_periodic_invoices_config' });
577 $.post("controller.pl", data, kivi.eval_json_result);
580 ns.check_save_active_periodic_invoices = function() {
581 var type = $('#type').val();
582 if (type !== 'sales_order') return true;
586 url: 'controller.pl',
587 data: { action: 'Order/get_has_active_periodic_invoices',
590 config: $('#order_periodic_invoices_config').val(),
595 success: function(val) {
601 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?'));
607 ns.show_vc_details_dialog = function() {
608 if (!ns.check_cv()) return;
612 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
614 vc_id = $('#order_customer_id').val();
615 title = kivi.t8('Customer details');
618 vc_id = $('#order_vendor_id').val();
619 title = kivi.t8('Vendor details');
623 url: 'controller.pl',
624 data: { action: 'Order/show_customer_vendor_details_dialog',
625 type : $('#type').val(),
629 id: 'jq_customer_vendor_details_dialog',
639 ns.show_calculate_qty_dialog = function(clicked) {
640 var row = $(clicked).parents("tbody").first();
641 var input_id = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
642 var formula_id = $(row).find('[name="formula[+]"]').attr('id');
644 calculate_qty_selection_dialog("", input_id, "", formula_id);
651 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
652 $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
654 $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
657 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
658 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
660 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
662 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
663 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
665 $('.add_item_input').keydown(function(event) {
666 if (event.keyCode == 13) {
667 event.preventDefault();
668 kivi.Order.add_item();
673 kivi.Order.init_row_handlers();
675 $('#row_table_id').on('sortstop', function(event, ui) {
676 $('#row_table_id thead a img').remove();
677 kivi.Order.renumber_positions();
680 $('#expand_all').on('click', function(event) {
681 event.preventDefault();
682 if ($('#expand_all').data('expanded') == 1) {
683 $('#expand_all').data('expanded', 0);
684 $('#expand_all').attr('src', 'image/expand.svg');
685 $('#expand_all').attr('alt', kivi.t8('Show all details'));
686 $('#expand_all').attr('title', kivi.t8('Show all details'));
687 $('.row_entry').each(function(idx, elt) {
688 kivi.Order.hide_second_row(elt);
691 $('#expand_all').data('expanded', 1);
692 $('#expand_all').attr('src', "image/collapse.svg");
693 $('#expand_all').attr('alt', kivi.t8('Hide all details'));
694 $('#expand_all').attr('title', kivi.t8('Hide all details'));
695 kivi.Order.load_all_second_rows();
696 $('.row_entry').each(function(idx, elt) {
697 kivi.Order.show_second_row(elt);