Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 91abaf6c

Von Bernd Bleßmann vor etwa 8 Jahren hinzugefügt

  • ID 91abaf6cbfa5bb429df7fce3748b3d37082551ad
  • Vorgänger 6550f507
  • Nachfolger 2d50590b

Auftrags-Controller: Mehrfach-Artikelauswahl mit Mengeneingabe.

Unterschiede anzeigen:

SL/Controller/Order.pm
20 20
use SL::DB::Default;
21 21
use SL::DB::Unit;
22 22
use SL::DB::Price;
23
use SL::DB::Part;
23 24

  
24 25
use SL::Helper::DateTime;
25 26
use SL::Helper::CreatePDF qw(:all);
26 27

  
28
use SL::Controller::Helper::GetModels;
29

  
27 30
use List::Util qw(max first);
28 31
use List::MoreUtils qw(none pairwise first_index);
29 32
use English qw(-no_match_vars);
......
31 34

  
32 35
use Rose::Object::MakeMethods::Generic
33 36
(
34
 'scalar --get_set_init' => [ qw(order valid_types type cv p) ],
37
 'scalar --get_set_init' => [ qw(order valid_types type cv p multi_items_models) ],
35 38
);
36 39

  
37 40

  
......
333 336

  
334 337
  return unless $form_attr->{parts_id};
335 338

  
336
  my $item = SL::DB::OrderItem->new;
337
  $item->assign_attributes(%$form_attr);
339
  my $item = _make_item($self->order, $form_attr);
340
  $self->order->add_items($item);
338 341

  
339
  my $part         = SL::DB::Part->new(id => $form_attr->{parts_id})->load;
342
  $self->_recalc();
340 343

  
341
  my $price_source = SL::PriceSource->new(record_item => $item, record => $self->order);
344
  my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
345
  my $row_as_html = $self->p->render('order/tabs/_row', ITEM => $item, ID => $item_id);
342 346

  
343
  my $price_src;
344
  if ($item->sellprice) {
345
    $price_src = $price_source->price_from_source("");
346
    $price_src->price($item->sellprice);
347
  } else {
348
    $price_src = $price_source->best_price
349
           ? $price_source->best_price
350
           : $price_source->price_from_source("");
351
    $price_src->price(0) if !$price_source->best_price;
352
  }
347
  $self->js
348
    ->append('#row_table_id', $row_as_html)
349
    ->val('.add_item_input', '')
350
    ->run('row_table_scroll_down')
351
    ->run('row_set_keyboard_events_by_id', $item_id)
352
    ->on('.recalc', 'change', 'recalc_amounts_and_taxes')
353
    ->on('.reformat_number', 'change', 'reformat_number')
354
    ->focus('#add_item_parts_id_name');
353 355

  
354
  my $discount_src;
355
  if ($item->discount) {
356
    $discount_src = $price_source->discount_from_source("");
357
    $discount_src->discount($item->discount);
356
  $self->_js_redisplay_amounts_and_taxes;
357
  $self->js->render();
358
}
359

  
360
sub action_show_multi_items_dialog {
361
  require SL::DB::PartsGroup;
362
  $_[0]->render('order/tabs/_multi_items_dialog', { layout => 0 },
363
                all_partsgroups => SL::DB::Manager::PartsGroup->get_all);
364
}
365

  
366
sub action_multi_items_update_result {
367
  my $max_count = 100;
368
  my $count = $_[0]->multi_items_models->count;
369

  
370
  if ($count == 0) {
371
    my $text = SL::Presenter::EscapedText->new(text => $::locale->text('No results.'));
372
    $_[0]->render($text, { layout => 0 });
373
  } elsif ($count > $max_count) {
374
    my $text = SL::Presenter::EscapedText->new(text => $::locale->text('Too many results (#1 from #2).', $count, $max_count));
375
    $_[0]->render($text, { layout => 0 });
358 376
  } else {
359
    $discount_src = $price_source->best_discount
360
                  ? $price_source->best_discount
361
                  : $price_source->discount_from_source("");
362
    $discount_src->discount(0) if !$price_source->best_discount;
377
    my $multi_items = $_[0]->multi_items_models->get;
378
    $_[0]->render('order/tabs/_multi_items_result', { layout => 0 },
379
                  multi_items => $multi_items);
363 380
  }
381
}
364 382

  
365
  my %new_attr;
366
  $new_attr{part}                   = $part;
367
  $new_attr{description}            = $part->description if ! $item->description;
368
  $new_attr{qty}                    = 1.0                if ! $item->qty;
369
  $new_attr{sellprice}              = $price_src->price;
370
  $new_attr{discount}               = $discount_src->discount;
371
  $new_attr{active_price_source}    = $price_src;
372
  $new_attr{active_discount_source} = $discount_src;
373

  
374
  # add_custom_variables adds cvars to an orderitem with no cvars for saving, but
375
  # they cannot be retrieved via custom_variables until the order/orderitem is
376
  # saved. Adding empty custom_variables to new orderitem here solves this problem.
377
  $new_attr{custom_variables} = [];
383
sub action_add_multi_items {
384
  my ($self) = @_;
378 385

  
379
  $item->assign_attributes(%new_attr);
386
  my @form_attr = grep { $_->{qty_as_number} } @{ $::form->{add_multi_items} };
387
  return $self->js->render() unless scalar @form_attr;
380 388

  
381
  $self->order->add_items($item);
389
  my @items;
390
  foreach my $attr (@form_attr) {
391
    push @items, _make_item($self->order, $attr);
392
  }
393
  $self->order->add_items(@items);
382 394

  
383 395
  $self->_recalc();
384 396

  
385
  my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
386
  my $row_as_html = $self->p->render('order/tabs/_row', ITEM => $item, ID => $item_id);
397
  foreach my $item (@items) {
398
    my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
399
    my $row_as_html = $self->p->render('order/tabs/_row', ITEM => $item, ID => $item_id);
400

  
401
    $self->js
402
        ->append('#row_table_id', $row_as_html)
403
        ->run('row_set_keyboard_events_by_id', $item_id);
404
  }
387 405

  
388 406
  $self->js
389
    ->append('#row_table_id', $row_as_html)
390
    ->val('.add_item_input', '')
407
    ->run('close_multi_items_dialog')
391 408
    ->run('row_table_scroll_down')
392
    ->run('row_set_keyboard_events_by_id', $item_id)
393 409
    ->on('.recalc', 'change', 'recalc_amounts_and_taxes')
394 410
    ->on('.reformat_number', 'change', 'reformat_number')
395 411
    ->focus('#add_item_parts_id_name');
......
483 499
  _make_order();
484 500
}
485 501

  
502
sub init_multi_items_models {
503
  SL::Controller::Helper::GetModels->new(
504
    controller     => $_[0],
505
    model          => 'Part',
506
    with_objects   => [ qw(unit_obj) ],
507
    disable_plugin => 'paginated',
508
    source         => $::form->{multi_items},
509
    sorted         => {
510
      _default    => {
511
        by  => 'partnumber',
512
        dir => 1,
513
      },
514
      partnumber  => t8('Partnumber'),
515
      description => t8('Description')}
516
  );
517
}
518

  
486 519
sub _check_auth {
487 520
  my ($self) = @_;
488 521

  
......
565 598
  return $order;
566 599
}
567 600

  
601
sub _make_item {
602
  my ($record, $attr) = @_;
603

  
604
  my $item = SL::DB::OrderItem->new;
605
  $item->assign_attributes(%$attr);
606

  
607
  my $part         = SL::DB::Part->new(id => $attr->{parts_id})->load;
608
  my $price_source = SL::PriceSource->new(record_item => $item, record => $record);
609

  
610
  $item->unit($part->unit) if !$item->unit;
611

  
612
  my $price_src;
613
  if ($item->sellprice) {
614
    $price_src = $price_source->price_from_source("");
615
    $price_src->price($item->sellprice);
616
  } else {
617
    $price_src = $price_source->best_price
618
           ? $price_source->best_price
619
           : $price_source->price_from_source("");
620
    $price_src->price(0) if !$price_source->best_price;
621
  }
622

  
623
  my $discount_src;
624
  if ($item->discount) {
625
    $discount_src = $price_source->discount_from_source("");
626
    $discount_src->discount($item->discount);
627
  } else {
628
    $discount_src = $price_source->best_discount
629
                  ? $price_source->best_discount
630
                  : $price_source->discount_from_source("");
631
    $discount_src->discount(0) if !$price_source->best_discount;
632
  }
633

  
634
  my %new_attr;
635
  $new_attr{part}                   = $part;
636
  $new_attr{description}            = $part->description if ! $item->description;
637
  $new_attr{qty}                    = 1.0                if ! $item->qty;
638
  $new_attr{sellprice}              = $price_src->price;
639
  $new_attr{discount}               = $discount_src->discount;
640
  $new_attr{active_price_source}    = $price_src;
641
  $new_attr{active_discount_source} = $discount_src;
642

  
643
  # add_custom_variables adds cvars to an orderitem with no cvars for saving, but
644
  # they cannot be retrieved via custom_variables until the order/orderitem is
645
  # saved. Adding empty custom_variables to new orderitem here solves this problem.
646
  $new_attr{custom_variables} = [];
647

  
648
  $item->assign_attributes(%new_attr);
649

  
650
  return $item;
651
}
652

  
568 653
sub _recalc {
569 654
  my ($self) = @_;
570 655

  
js/locale/de.js
2 2
"A transaction description is required.":"Die Vorgangsbezeichnung muss eingegeben werden.",
3 3
"Add function block":"Funktionsblock hinzufügen",
4 4
"Add linked record":"Verknüpften Beleg hinzufügen",
5
"Add multiple items":"Mehrere Artikel hinzufügen",
5 6
"Add picture":"Bild hinzufügen",
6 7
"Add picture to text block":"Bild dem Textblock hinzufügen",
7 8
"Add section":"Abschnitt hinzufügen",
locale/de/all
187 187
  'Add link: select records to link with' => 'Verknüpfungen hinzufügen: zu verknüpfende Belege auswählen',
188 188
  'Add linked record'           => 'Verknüpften Beleg hinzufügen',
189 189
  'Add links'                   => 'Verknüpfungen hinzufügen',
190
  'Add multiple items'          => 'Mehrere Artikel hinzufügen',
190 191
  'Add new currency'            => 'Neue Währung hinzufügen',
191 192
  'Add new custom variable'     => 'Neue benutzerdefinierte Variable erfassen',
192 193
  'Add new price rule item'     => 'Neue Bedingung hinzufügen',
......
1783 1784
  'No requirement spec statuses has been created yet.' => 'Es wurden noch keine Pflichtenheftstatus angelegt.',
1784 1785
  'No requirement spec templates have been created yet.' => 'Es wurden noch keine Pflichtenheftvorlagen angelegt.',
1785 1786
  'No requirement spec type has been created yet.' => 'Es wurden noch keine Pflichtenhefttypen angelegt.',
1787
  'No results.'                 => 'Keine Artikel',
1786 1788
  'No risks level has been created yet.' => 'Es wurden noch keine Risikograde angelegt.',
1787 1789
  'No sections created yet'     => 'Keine Abschnitte erstellt',
1788 1790
  'No sections have been created so far.' => 'Bisher wurden noch keine Abschnitte angelegt.',
......
3079 3081
  'To continue please change the taxkey 0 to another value.' => 'Um fortzufahren, ändern Sie bitte den Steuerschlüssel 0 auf einen anderen Wert.',
3080 3082
  'To user login'               => 'Zum Benutzerlogin',
3081 3083
  'Toggle marker'               => 'Markierung umschalten',
3084
  'Too many results (#1 from #2).' => 'Zu viele Artikel (#1 von #2)',
3082 3085
  'Top'                         => 'Oben',
3083 3086
  'Top (CSS)'                   => 'Oben (mit CSS)',
3084 3087
  'Top (Javascript)'            => 'Oben (mit Javascript)',
......
3424 3427
  'follow_up_list'              => 'wiedervorlageliste',
3425 3428
  'for'                         => 'für',
3426 3429
  'for Period'                  => 'für den Zeitraum',
3430
  'for all'                     => 'für alle',
3427 3431
  'for date'                    => 'zum Stichtag',
3428 3432
  'found'                       => 'Gefunden',
3429 3433
  'from (time)'                 => 'von',
templates/webpages/order/tabs/_multi_items_dialog.html
1
[%- USE T8 %][%- USE HTML %][%- USE L %][%- USE LxERP %]
2

  
3
<form method="post" id="multi_items_form" method="POST">
4

  
5
<table id='multi_items_filter_table'>
6
  <tr>
7
    <th>[%- LxERP.t8("Description") %]/[%- LxERP.t8("Partnumber") %]:</th>
8
    <td>[%- L.input_tag('multi_items.filter.all:substr:multi::ilike', '') %]</td>
9
    <th>[%- LxERP.t8("Group") %]</th>
10
    <td>[%- L.select_tag('multi_items.filter.partsgroup_id', all_partsgroups, title_key='displayable_name', value_key='id', with_empty=1) %]</td>
11
  <tr>
12
</table>
13

  
14
[% L.button_tag('update_result()', LxERP.t8('Filter')) %]
15
<a href='#' onClick='javascript:$("#multi_items_filter_table input").val("");$("#multi_items_filter_table input[type=checkbox]").prop("checked", 0);$("#multi_items_filter_table select").prop("selectedIndex", 0);'>[% 'Reset' | $T8 %]</a>
16

  
17
<hr>
18
<div id='multi_items_result'></div>
19
<hr>
20

  
21
[% L.button_tag('add_multi_items()', LxERP.t8('Continue')) %]
22
<a href="#" onclick="close_multi_items_dialog();">[%- LxERP.t8("Cancel") %]</a>
23

  
24
<script type='text/javascript'>
25
function update_result() {
26
  var data = $('#multi_items_form').serialize();
27
  data += '&type=[%- FORM.type %]';
28
  $.ajax({
29
    url: 'controller.pl?action=Order/multi_items_update_result',
30
    data: data,
31
    method: 'post',
32
    success: function(data){
33
      $('#multi_items_result').html(data);
34
      $('#multi_items_result input').keydown(function(event) {
35
        if(event.keyCode == 13) {
36
          event.preventDefault();
37
          add_multi_items();
38
          return false;
39
        }
40
      });
41
    }
42
  });
43
}
44

  
45
function add_multi_items() {
46
  var data = $('#[%- FORM.callback_data_id %]').serialize();
47
  data += '&';
48
  data += $('#multi_items_form').serialize();
49
  data += '&action=[%- FORM.callback %]';
50
  $.post("controller.pl", data, kivi.eval_json_result);
51
}
52

  
53
$('#multi_items_filter_table input, #multi_items_filter_table select').keydown(function(event) {
54
  if(event.keyCode == 13) {
55
    event.preventDefault();
56
    update_result();
57
    return false;
58
  }
59
});
60

  
61
$('#multi_items_filter_all_substr_multi_ilike').focus();
62
</script>
63

  
64
</form>
templates/webpages/order/tabs/_multi_items_result.html
1
[%- USE T8 %][%- USE HTML %][%- USE L %][%- USE LxERP %]
2

  
3
<table width="100%">
4
    <tr>
5
      <td>[% 'for all' | $T8 %]
6
      <td>[% L.input_tag("multi_items.all_qty", '', size = 5, style='text-align:right') %]</td>
7
    </tr>
8
    <tr>
9
      <td colspan="5"><hr></td>
10
    </tr>
11
  [%- FOREACH item = multi_items %]
12
    <tr>
13
      <td></td>
14
      <td>
15
        [% L.hidden_tag("add_multi_items[+].parts_id", item.id) %]
16
        [% L.input_tag("add_multi_items[].qty_as_number", '', size = 5, style='text-align:right',
17
                       class = 'multi_items_qty', onclick = 'set_qty_to_one(this)') %]
18
      </td>
19
      <td>[% HTML.escape(item.unit) %]</td>
20
      <td>[% HTML.escape(item.partnumber) %]</td>
21
      <td>[% HTML.escape(item.description) %]</td>
22
    </tr>
23
  [%- END %]
24
</table>
25

  
26
<script type='text/javascript'>
27
  function set_qty_to_one(clicked) {
28
    if ($(clicked).val() == '') {
29
      $(clicked).val('[%- LxERP.format_amount(1.00, -2) %]');
30
    }
31
    $(clicked).select();
32
  }
33

  
34
  $('#multi_items_all_qty').change(function(event){
35
    $('.multi_items_qty').val($(event.target).val());
36
  });
37
</script>
templates/webpages/order/tabs/basic_data.html
143 143

  
144 144
  [%- PROCESS order/tabs/_item_input.html %]
145 145

  
146
  [% L.button_tag('show_multi_items_dialog()', LxERP.t8('Add multiple parts')) %]</td>
147

  
146 148
  <table width="100%">
147 149
    <tr>
148 150
      <td>
......
280 282
  $.post("controller.pl", data, kivi.eval_json_result);
281 283
}
282 284

  
285
function show_multi_items_dialog() {
286
  if (!check_cv()) return;
287

  
288
  kivi.popup_dialog({
289
    url: 'controller.pl?action=Order/show_multi_items_dialog',
290
    data: { type: $('#type').val(),
291
            callback: 'Order/add_multi_items',
292
            callback_data_id: 'order_form' },
293
    id: 'jq_multi_items_dialog',
294
    dialog: {
295
      title: kivi.t8('Add multiple items'),
296
      width:  800,
297
      height: 500
298
    }
299
  });
300
  return true;
301
}
302

  
303
function close_multi_items_dialog() {
304
  $('#jq_multi_items_dialog').dialog('close');
305
};
306

  
283 307
function delete_order_item_row(clicked) {
284 308
  var row = $(clicked).parents("tbody").first();
285 309
  $(row).remove();

Auch abrufbar als: Unified diff