Auftrags-Controller: Belegnummer in Titlezeile anzeigen
[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_save_duplicate_parts = function() {
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       return confirm(kivi.t8("There are duplicate parts at positions") + "\n"
32                      + pos.join(', ') + "\n"
33                      + kivi.t8("Do you really want to save?"));
34     }
35     return true;
36   };
37
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;
41
42     var data = $('#order_form').serializeArray();
43     data.push({ name: 'action', value: 'Order/' + action });
44
45     $.post("controller.pl", data, kivi.eval_json_result);
46   };
47
48   ns.delete_order = function() {
49     var data = $('#order_form').serializeArray();
50     data.push({ name: 'action', value: 'Order/delete' });
51
52     $.post("controller.pl", data, kivi.eval_json_result);
53   };
54
55   ns.show_print_options = function() {
56     if (!ns.check_cv()) return;
57
58     kivi.popup_dialog({
59       id: 'print_options',
60       dialog: {
61         title: kivi.t8('Print options'),
62         width:  800,
63         height: 300
64       }
65     });
66   };
67
68   ns.print = function() {
69     $('#print_options').dialog('close');
70
71     var data = $('#order_form').serializeArray();
72     data = data.concat($('#print_options_form').serializeArray());
73     data.push({ name: 'action', value: 'Order/print' });
74
75     $.post("controller.pl", data, kivi.eval_json_result);
76   };
77
78   ns.download_pdf = function(pdf_filename, key) {
79     var data = [];
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);
85   };
86
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' });
91
92     $.post("controller.pl", data, kivi.eval_json_result);
93   };
94
95   var email_dialog;
96
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);
100
101     $('#print_options_form table').first().remove().appendTo('#email_form_print_options');
102
103     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
104     $('#email_form_' + to_focus).focus();
105   };
106
107   ns.finish_send_email_dialog = function() {
108     kivi.SalesPurchase.show_all_print_options_elements();
109
110     $('#email_form_print_options table').first().remove().prependTo('#print_options_form');
111     return true;
112   };
113
114   ns.show_email_dialog = function(html) {
115     var id            = 'send_email_dialog';
116     var dialog_params = {
117       id:     id,
118       width:  800,
119       height: 600,
120       title:  kivi.t8('Send email'),
121       modal:  true,
122       beforeClose: kivi.Order.finish_send_email_dialog,
123       close: function(event, ui) {
124         email_dialog.remove();
125       }
126     };
127
128     $('#' + id).remove();
129
130     email_dialog = $('<div style="display:none" id="' + id + '"></div>').appendTo('body');
131     email_dialog.html(html);
132     email_dialog.dialog(dialog_params);
133
134     kivi.Order.setup_send_email_dialog();
135
136     $('.cancel').click(ns.close_email_dialog);
137
138     return true;
139   };
140
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);
147   };
148
149   ns.close_email_dialog = function() {
150     email_dialog.dialog("close");
151   };
152
153   ns.set_number_in_title = function(elt) {
154     $('#nr_in_title').html($(elt).val());
155   };
156
157   ns.reload_cv_dependant_selections = function() {
158     var data = $('#order_form').serializeArray();
159     data.push({ name: 'action', value: 'Order/customer_vendor_changed' });
160
161     $.post("controller.pl", data, kivi.eval_json_result);
162   };
163
164   ns.reformat_number = function(event) {
165     $(event.target).val(kivi.format_amount(kivi.parse_amount($(event.target).val()), -2));
166   };
167
168   ns.recalc_amounts_and_taxes = function() {
169     var data = $('#order_form').serializeArray();
170     data.push({ name: 'action', value: 'Order/recalc_amounts_and_taxes' });
171
172     $.post("controller.pl", data, kivi.eval_json_result);
173   };
174
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"]');
180
181     var oldval = $(select_elt).data('oldval');
182     $(select_elt).data('oldval', $(select_elt).val());
183
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') });
189
190     $.post("controller.pl", data, kivi.eval_json_result);
191   };
192
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);
199   };
200
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"]');
204
205     if ($(div_elt).data('loaded') == 1) {
206       return;
207     }
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() });
211
212     $.post("controller.pl", data, kivi.eval_json_result);
213   };
214
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;
218     });
219
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 };
223     });
224
225     if (item_ids.length == 0) {
226       return;
227     }
228
229     var data = $('#order_form').serializeArray();
230     data.push({ name: 'action', value: 'Order/load_second_rows' });
231     data = data.concat(item_ids);
232
233     $.post("controller.pl", data, kivi.eval_json_result);
234   };
235
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'));
243   };
244
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'));
252   };
253
254   ns.toggle_second_row = function(row) {
255     if ($(row).data('expanded') == 1) {
256       ns.hide_second_row(row);
257     } else {
258       ns.show_second_row(row);
259     }
260   };
261
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);
265     });
266
267     kivi.run_once_for('.reformat_number', 'on_change_reformat', function(elt) {
268       $(elt).change(ns.reformat_number);
269     });
270
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);
274     });
275
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) {
279           // shift arrow down
280           event.preventDefault();
281           var row = $(event.target).parents(".row_entry").first();
282           ns.load_second_row(row);
283           ns.show_second_row(row);
284           return false;
285         }
286         if(event.keyCode == 38 && event.shiftKey === true) {
287           // shift arrow up
288           event.preventDefault();
289           var row = $(event.target).parents(".row_entry").first();
290           ns.hide_second_row(row);
291           return false;
292         }
293       });
294     });
295
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);
302         return false;
303       })
304     });
305
306   };
307
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];
314         var h  = '<span';
315         if (mt[0] === '-') h += ' class="plus0"';
316         h += '>' + mt + '&nbsp;&nbsp;' + mp + '%';
317         h += '</span>';
318         $(elt).find('[name="linemargin"]').html(h);
319       }
320     });
321   };
322
323   ns.renumber_positions = function() {
324     $('.row_entry [name="position"]').each(function(idx, elt) {
325       $(elt).html(idx+1);
326     });
327   };
328
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();
332
333     var src;
334     if (dir == "1") {
335       dir = "0";
336       src = "image/up.png";
337     } else {
338       dir = "1";
339       src = "image/down.png";
340     }
341
342     $('#' + order_by + '_header_id a').append('<img border=0 data-sort-dir=' + dir + ' src=' + src + ' alt="' + kivi.t8('sort items') + '">');
343
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 });
348
349     $.post("controller.pl", data, kivi.eval_json_result);
350   };
351
352   ns.redisplay_items = function(data) {
353     var old_rows = $('.row_entry').detach();
354     var new_rows = [];
355     $(data).each(function(idx, elt) {
356       new_rows.push(old_rows[elt.old_pos - 1]);
357     });
358     $(new_rows).appendTo($('#row_table_id'));
359     ns.renumber_positions();
360   };
361
362   ns.add_item = function() {
363     if ($('#add_item_parts_id').val() === '') return;
364     if (!ns.check_cv()) return;
365
366     $('#row_table_id thead a img').remove();
367
368     var data = $('#order_form').serializeArray();
369     data.push({ name: 'action', value: 'Order/add_item' });
370
371     $.post("controller.pl", data, kivi.eval_json_result);
372   };
373
374   ns.show_multi_items_dialog = function() {
375     if (!ns.check_cv()) return;
376
377     $('#row_table_id thead a img').remove();
378
379     kivi.popup_dialog({
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',
385       dialog: {
386         title: kivi.t8('Add multiple items'),
387         width:  800,
388         height: 500
389       }
390     });
391     return true;
392   };
393
394   ns.close_multi_items_dialog = function() {
395     $('#jq_multi_items_dialog').dialog('close');
396   };
397
398   ns.delete_order_item_row = function(clicked) {
399     var row = $(clicked).parents("tbody").first();
400     $(row).remove();
401
402     ns.renumber_positions();
403     ns.recalc_amounts_and_taxes();
404   };
405
406   ns.row_table_scroll_down = function() {
407     $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
408   };
409
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"]');
417     var longdescription;
418
419     if (!longdescription_elt.length) {
420       var data = [];
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() });
425       $.ajax({
426         url: 'controller.pl',
427         data: data,
428         method: "GET",
429         async: false,
430         dataType: 'text',
431         success: function(val){
432           longdescription = val;
433         }
434       });
435     } else {
436       longdescription = longdescription_elt.val();
437     }
438
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);
446                    }
447                  };
448
449     kivi.SalesPurchase.edit_longdescription_with_params(params);
450   };
451
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[+]"]');
455
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() });
459
460     $.post("controller.pl", data, kivi.eval_json_result);
461   };
462
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"]');
467
468     button_elt.val(button_elt.val().replace(/.*\|/, descr + " |"));
469     source_elt.val(source);
470
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 === '') {
474       // editable
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);
479     } else {
480       // not editable
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);
485     }
486
487     if (price_str) {
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();
493     }
494
495     kivi.io.close_dialog();
496   };
497
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"]');
502
503     button_elt.val(button_elt.val().replace(/\|.*/, "| " + descr));
504     source_elt.val(source);
505
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 === '') {
509       // editable
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);
514     } else {
515       // not editable
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);
520     }
521
522     if (discount_str) {
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();
528     }
529
530     kivi.io.close_dialog();
531   };
532
533   ns.show_periodic_invoices_config_dialog = function() {
534     if ($('#type').val() !== 'sales_order') return;
535
536     kivi.popup_dialog({
537       url: 'controller.pl?action=Order/show_periodic_invoices_config_dialog',
538       data: { type       : $('#type').val(),
539               id         : $('#id').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()
544             },
545       id: 'jq_periodic_invoices_config_dialog',
546       load: kivi.reinit_widgets,
547       dialog: {
548         title: kivi.t8('Edit the configuration for periodic invoices'),
549         width:  800,
550         height: 650
551       }
552     });
553     return true;
554   };
555
556   ns.close_periodic_invoices_config_dialog = function() {
557     $('#jq_periodic_invoices_config_dialog').dialog('close');
558   };
559
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);
565   };
566
567   ns.check_save_active_periodic_invoices = function() {
568     var type = $('#type').val();
569     if (type !== 'sales_order') return true;
570
571     var active = false;
572     $.ajax({
573       url: 'controller.pl',
574       data: { action: 'Order/get_has_active_periodic_invoices',
575               type  : type,
576               id    : $('#id').val(),
577               config: $('#order_periodic_invoices_config').val(),
578       },
579       method: "GET",
580       async: false,
581       dataType: 'text',
582       success: function(val){
583         active = val;
584       }
585     });
586
587     if (active == 1) {
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?'));
589     }
590
591     return true;
592   };
593
594 });
595
596 $(function(){
597   if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
598     $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
599   } else {
600     $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
601   }
602
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)) });
605   } else {
606     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
607   }
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) });
610
611   $('.add_item_input').keydown(function(event) {
612     if(event.keyCode == 13) {
613       event.preventDefault();
614       kivi.Order.add_item();
615       return false;
616     }
617   });
618
619   kivi.Order.init_row_handlers();
620
621   $('#row_table_id').on('sortstop', function(event, ui) {
622     $('#row_table_id thead a img').remove();
623     kivi.Order.renumber_positions();
624   });
625
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);
635       });
636     } else {
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);
644       });
645     }
646     return false;
647   });
648
649 });