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) {
90 data.push({ name: 'action', value: 'Order/download_pdf' });
91 data.push({ name: 'type', value: $('#type').val() });
92 data.push({ name: 'pdf_filename', value: pdf_filename });
93 data.push({ name: 'key', value: key });
94 $.download("controller.pl", data);
97 ns.email = function() {
98 if (!ns.check_cv()) return;
99 var data = $('#order_form').serializeArray();
100 data.push({ name: 'action', value: 'Order/show_email_dialog' });
102 $.post("controller.pl", data, kivi.eval_json_result);
107 ns.setup_send_email_dialog = function() {
108 kivi.SalesPurchase.show_all_print_options_elements();
109 kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false);
111 $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
113 var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
114 $('#email_form_' + to_focus).focus();
117 ns.finish_send_email_dialog = function() {
118 kivi.SalesPurchase.show_all_print_options_elements();
120 $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
124 ns.show_email_dialog = function(html) {
125 var id = 'send_email_dialog';
126 var dialog_params = {
130 title: kivi.t8('Send email'),
132 beforeClose: kivi.Order.finish_send_email_dialog,
133 close: function(event, ui) {
134 email_dialog.remove();
138 $('#' + id).remove();
140 email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
141 email_dialog.html(html);
142 email_dialog.dialog(dialog_params);
144 kivi.Order.setup_send_email_dialog();
146 $('.cancel').click(ns.close_email_dialog);
151 ns.send_email = function() {
152 var data = $('#order_form').serializeArray();
153 data = data.concat($('[name^="email_form."]').serializeArray());
154 data = data.concat($('[name^="print_options."]').serializeArray());
155 data.push({ name: 'action', value: 'Order/send_email' });
156 $.post("controller.pl", data, kivi.eval_json_result);
159 ns.close_email_dialog = function() {
160 email_dialog.dialog("close");
163 ns.set_number_in_title = function(elt) {
164 $('#nr_in_title').html($(elt).val());
167 ns.reload_cv_dependant_selections = function() {
168 var data = $('#order_form').serializeArray();
169 data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
171 $.post("controller.pl", data, kivi.eval_json_result);
174 ns.reformat_number = function(event) {
175 $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
178 ns.recalc_amounts_and_taxes = function() {
179 var data = $('#order_form').serializeArray();
180 data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
182 $.post("controller.pl", data, kivi.eval_json_result);
185 ns.unit_change = function(event) {
186 var row = $(event.target).parents("tbody").first();
187 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
188 var sellprice_dom = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
189 var select_elt = $(row).find('[name="order.orderitems[].unit"]');
191 var oldval = $(select_elt).data('oldval');
192 $(select_elt).data('oldval', $(select_elt).val());
194 var data = $('#order_form').serializeArray();
195 data.push({ name: 'action', value: 'Order/unit_changed' });
196 data.push({ name: 'item_id', value: item_id_dom.val() });
197 data.push({ name: 'old_unit', value: oldval });
198 data.push({ name: 'sellprice_dom_id', value: sellprice_dom.attr('id') });
200 $.post("controller.pl", data, kivi.eval_json_result);
203 ns.update_sellprice = function(item_id, price_str) {
204 var row = $('#item_' + item_id).parents("tbody").first();
205 var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
206 var html_elt = $(row).find('[name="sellprice_text"]');
207 price_elt.val(price_str);
208 html_elt.html(price_str);
211 ns.load_second_row = function(row) {
212 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
213 var div_elt = $(row).find('[name="second_row"]');
215 if ($(div_elt).data('loaded') == 1) {
218 var data = $('#order_form').serializeArray();
219 data.push({ name: 'action', value: 'Order/load_second_rows' });
220 data.push({ name: 'item_ids[]', value: item_id_dom.val() });
222 $.post("controller.pl", data, kivi.eval_json_result);
225 ns.load_all_second_rows = function() {
226 var rows = $('.row_entry').filter(function(idx, elt) {
227 return $(elt).find('[name="second_row"]').data('loaded') != 1;
230 var item_ids = $.map(rows, function(elt) {
231 var item_id = $(elt).find('[name="orderitem_ids[+]"]').val();
232 return { name: 'item_ids[]', value: item_id };
235 if (item_ids.length == 0) {
239 var data = $('#order_form').serializeArray();
240 data.push({ name: 'action', value: 'Order/load_second_rows' });
241 data = data.concat(item_ids);
243 $.post("controller.pl", data, kivi.eval_json_result);
246 ns.hide_second_row = function(row) {
247 $(row).children().not(':first').hide();
248 $(row).data('expanded', 0);
249 var elt = $(row).find('.expand');
250 elt.attr('src', "image/expand.svg");
251 elt.attr('alt', kivi.t8('Show details'));
252 elt.attr('title', kivi.t8('Show details'));
255 ns.show_second_row = function(row) {
256 $(row).children().not(':first').show();
257 $(row).data('expanded', 1);
258 var elt = $(row).find('.expand');
259 elt.attr('src', "image/collapse.svg");
260 elt.attr('alt', kivi.t8('Hide details'));
261 elt.attr('title', kivi.t8('Hide details'));
264 ns.toggle_second_row = function(row) {
265 if ($(row).data('expanded') == 1) {
266 ns.hide_second_row(row);
268 ns.show_second_row(row);
272 ns.init_row_handlers = function() {
273 kivi.run_once_for('.recalc', 'on_change_recalc', function(elt) {
274 $(elt).change(ns.recalc_amounts_and_taxes);
277 kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
278 $(elt).change(ns.reformat_number);
281 kivi.run_once_for('.unitselect', 'on_change_unit_with_oldval', function(elt) {
282 $(elt).data('oldval', $(elt).val());
283 $(elt).change(ns.unit_change);
286 kivi.run_once_for('.row_entry', 'on_kbd_click_show_hide', function(elt) {
287 $(elt).keydown(function(event) {
288 if(event.keyCode == 40 && event.shiftKey === true) {
290 event.preventDefault();
291 var row = $(event.target).parents(".row_entry").first();
292 ns.load_second_row(row);
293 ns.show_second_row(row);
296 if(event.keyCode == 38 && event.shiftKey === true) {
298 event.preventDefault();
299 var row = $(event.target).parents(".row_entry").first();
300 ns.hide_second_row(row);
306 kivi.run_once_for('.expand', 'expand_second_row', function(elt) {
307 $(elt).click(function(event) {
308 event.preventDefault();
309 var row = $(event.target).parents(".row_entry").first();
310 ns.load_second_row(row);
311 ns.toggle_second_row(row);
318 ns.redisplay_line_values = function(is_sales, data) {
319 $('.row_entry').each(function(idx, elt) {
320 $(elt).find('[name="linetotal"]').html(data[idx][0]);
321 if (is_sales && $(elt).find('[name="second_row"]').data('loaded') == 1) {
322 var mt = data[idx][1];
323 var mp = data[idx][2];
325 if (mt[0] === '-') h += ' class="plus0"';
326 h += '>' + mt + ' ' + mp + '%';
328 $(elt).find('[name="linemargin"]').html(h);
333 ns.renumber_positions = function() {
334 $('.row_entry [name="position"]').each(function(idx, elt) {
339 ns.reorder_items = function(order_by) {
340 var dir = $('#' + order_by + '_header_id a img').attr("data-sort-dir");
341 $('#row_table_id thead a img').remove();
346 src = "image/up.png";
349 src = "image/down.png";
352 $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
354 var data = $('#order_form').serializeArray();
355 data.push({ name: 'action', value: 'Order/reorder_items' });
356 data.push({ name: 'order_by', value: order_by });
357 data.push({ name: 'sort_dir', value: dir });
359 $.post("controller.pl", data, kivi.eval_json_result);
362 ns.redisplay_items = function(data) {
363 var old_rows = $('.row_entry').detach();
365 $(data).each(function(idx, elt) {
366 new_rows.push(old_rows[elt.old_pos - 1]);
368 $(new_rows).appendTo($('#row_table_id'));
369 ns.renumber_positions();
372 ns.add_item = function() {
373 if ($('#add_item_parts_id').val() === '') return;
374 if (!ns.check_cv()) return;
376 $('#row_table_id thead a img').remove();
378 var data = $('#order_form').serializeArray();
379 data.push({ name: 'action', value: 'Order/add_item' });
381 $.post("controller.pl", data, kivi.eval_json_result);
384 ns.show_multi_items_dialog = function() {
385 if (!ns.check_cv()) return;
387 $('#row_table_id thead a img').remove();
390 url: 'controller.pl?action=Order/show_multi_items_dialog',
391 data: { type: $('#type').val(),
392 callback: 'Order/add_multi_items',
393 callback_data_id: 'order_form' },
394 id: 'jq_multi_items_dialog',
396 title: kivi.t8('Add multiple items'),
404 ns.close_multi_items_dialog = function() {
405 $('#jq_multi_items_dialog').dialog('close');
408 ns.delete_order_item_row = function(clicked) {
409 var row = $(clicked).parents("tbody").first();
412 ns.renumber_positions();
413 ns.recalc_amounts_and_taxes();
416 ns.row_table_scroll_down = function() {
417 $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
420 ns.show_longdescription_dialog = function(clicked) {
421 var row = $(clicked).parents("tbody").first();
422 var position = $(row).find('[name="position"]').html();
423 var partnumber = $(row).find('[name="partnumber"]').html();
424 var description_elt = $(row).find('[name="order.orderitems[].description"]');
425 var description = description_elt.val();
426 var longdescription_elt = $(row).find('[name="order.orderitems[].longdescription"]');
429 if (!longdescription_elt.length) {
431 data.push({ name: 'action', value: 'Order/get_item_longdescription' });
432 data.push({ name: 'type', value: $('#type').val() });
433 data.push({ name: 'item_id', value: $(row).find('[name="order.orderitems[+].id"]').val() });
434 data.push({ name: 'parts_id', value: $(row).find('[name="order.orderitems[].parts_id"]').val() });
436 url: 'controller.pl',
441 success: function(val){
442 longdescription = val;
446 longdescription = longdescription_elt.val();
449 var params = { runningnumber: position,
450 partnumber: partnumber,
451 description: description,
452 default_longdescription: longdescription,
453 set_function: function(val){
454 longdescription_elt.remove();
455 $('<input type="hidden" name="order.orderitems[].longdescription">').insertAfter(description_elt).val(val);
459 kivi.SalesPurchase.edit_longdescription_with_params(params);
462 ns.price_chooser_item_row = function(clicked) {
463 if (!ns.check_cv()) return;
464 var row = $(clicked).parents("tbody").first();
465 var item_id_dom = $(row).find('[name="orderitem_ids[+]"]');
467 var data = $('#order_form').serializeArray();
468 data.push({ name: 'action', value: 'Order/price_popup' });
469 data.push({ name: 'item_id', value: item_id_dom.val() });
471 $.post("controller.pl", data, kivi.eval_json_result);
474 ns.update_price_source = function(item_id, source, descr, price_str, price_editable) {
475 var row = $('#item_' + item_id).parents("tbody").first();
476 var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]');
477 var button_elt = $(row).find('[name="price_chooser_button"]');
479 button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
480 source_elt.val(source);
482 var editable_div_elt = $(row).find('[name="editable_price"]');
483 var not_editable_div_elt = $(row).find('[name="not_editable_price"]');
484 if (price_editable == 1 && source === '') {
486 $(editable_div_elt).show();
487 $(not_editable_div_elt).hide();
488 $(editable_div_elt).find(':input').prop("disabled", false);
489 $(not_editable_div_elt).find(':input').prop("disabled", true);
492 $(editable_div_elt).hide();
493 $(not_editable_div_elt).show();
494 $(editable_div_elt).find(':input').prop("disabled", true);
495 $(not_editable_div_elt).find(':input').prop("disabled", false);
499 var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]');
500 var html_elt = $(row).find('[name="sellprice_text"]');
501 price_elt.val(price_str);
502 html_elt.html(price_str);
503 ns.recalc_amounts_and_taxes();
506 kivi.io.close_dialog();
509 ns.update_discount_source = function(item_id, source, descr, discount_str, price_editable) {
510 var row = $('#item_' + item_id).parents("tbody").first();
511 var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]');
512 var button_elt = $(row).find('[name="price_chooser_button"]');
514 button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
515 source_elt.val(source);
517 var editable_div_elt = $(row).find('[name="editable_discount"]');
518 var not_editable_div_elt = $(row).find('[name="not_editable_discount"]');
519 if (price_editable == 1 && source === '') {
521 $(editable_div_elt).show();
522 $(not_editable_div_elt).hide();
523 $(editable_div_elt).find(':input').prop("disabled", false);
524 $(not_editable_div_elt).find(':input').prop("disabled", true);
527 $(editable_div_elt).hide();
528 $(not_editable_div_elt).show();
529 $(editable_div_elt).find(':input').prop("disabled", true);
530 $(not_editable_div_elt).find(':input').prop("disabled", false);
534 var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]');
535 var html_elt = $(row).find('[name="discount_text"]');
536 discount_elt.val(discount_str);
537 html_elt.html(discount_str);
538 ns.recalc_amounts_and_taxes();
541 kivi.io.close_dialog();
544 ns.show_periodic_invoices_config_dialog = function() {
545 if ($('#type').val() !== 'sales_order') return;
548 url: 'controller.pl?action=Order/show_periodic_invoices_config_dialog',
549 data: { type : $('#type').val(),
551 config : $('#order_periodic_invoices_config').val(),
552 customer_id: $('#order_customer_id').val(),
553 transdate : $('#order_transdate').val(),
554 language_id: $('#language_id').val()
556 id: 'jq_periodic_invoices_config_dialog',
557 load: kivi.reinit_widgets,
559 title: kivi.t8('Edit the configuration for periodic invoices'),
567 ns.close_periodic_invoices_config_dialog = function() {
568 $('#jq_periodic_invoices_config_dialog').dialog('close');
571 ns.assign_periodic_invoices_config = function() {
572 var data = $('[name="Form"]').serializeArray();
573 data.push({ name: 'type', value: $('#type').val() });
574 data.push({ name: 'action', value: 'Order/assign_periodic_invoices_config' });
575 $.post("controller.pl", data, kivi.eval_json_result);
578 ns.check_save_active_periodic_invoices = function() {
579 var type = $('#type').val();
580 if (type !== 'sales_order') return true;
584 url: 'controller.pl',
585 data: { action: 'Order/get_has_active_periodic_invoices',
588 config: $('#order_periodic_invoices_config').val(),
593 success: function(val){
599 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?'));
605 ns.show_vc_details_dialog = function() {
606 if (!ns.check_cv()) return;
610 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
612 vc_id = $('#order_customer_id').val();
613 title = kivi.t8('Customer details');
616 vc_id = $('#order_vendor_id').val();
617 title = kivi.t8('Vendor details');
621 url: 'controller.pl',
622 data: { action: 'Order/show_customer_vendor_details_dialog',
623 type : $('#type').val(),
627 id: 'jq_customer_vendor_details_dialog',
637 ns.show_calculate_qty_dialog = function(clicked) {
638 var row = $(clicked).parents("tbody").first();
639 var input_id = $(row).find('[name="order.orderitems[].qty_as_number"]').attr('id');
640 var formula_id = $(row).find('[name="formula[+]"]').attr('id');
642 calculate_qty_selection_dialog("", input_id, "", formula_id);
649 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
650 $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
652 $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
655 if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
656 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
658 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
660 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
661 $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) });
663 $('.add_item_input').keydown(function(event) {
664 if(event.keyCode == 13) {
665 event.preventDefault();
666 kivi.Order.add_item();
671 kivi.Order.init_row_handlers();
673 $('#row_table_id').on('sortstop', function(event, ui) {
674 $('#row_table_id thead a img').remove();
675 kivi.Order.renumber_positions();
678 $('#expand_all').on('click', function(event) {
679 event.preventDefault();
680 if ($('#expand_all').data('expanded') == 1) {
681 $('#expand_all').data('expanded', 0);
682 $('#expand_all').attr('src', 'image/expand.svg');
683 $('#expand_all').attr('alt', kivi.t8('Show all details'));
684 $('#expand_all').attr('title', kivi.t8('Show all details'));
685 $('.row_entry').each(function(idx, elt) {
686 kivi.Order.hide_second_row(elt);
689 $('#expand_all').data('expanded', 1);
690 $('#expand_all').attr('src', "image/collapse.svg");
691 $('#expand_all').attr('alt', kivi.t8('Hide all details'));
692 $('#expand_all').attr('title', kivi.t8('Hide all details'));
693 kivi.Order.load_all_second_rows();
694 $('.row_entry').each(function(idx, elt) {
695 kivi.Order.show_second_row(elt);