Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 099fc63b

Von Bernd Bleßmann vor fast 9 Jahren hinzugefügt

  • ID 099fc63b531b1d4495cfab535ffd296d6a62ca0a
  • Vorgänger a84a030e
  • Nachfolger da55cfa0

Auftrags-Controller: neue Eingabemakse für Aufträge basierend auf Controller

Unterschiede anzeigen:

SL/Controller/Order.pm
1
package SL::Controller::Order;
2

  
3
use strict;
4
use parent qw(SL::Controller::Base);
5

  
6
use SL::Helper::Flash;
7
use SL::Presenter;
8
use SL::PriceSource;
9

  
10
use SL::DB::Order;
11
use SL::DB::Customer;
12
use SL::DB::Vendor;
13
use SL::DB::TaxZone;
14
use SL::DB::Employee;
15
use SL::DB::Project;
16
use SL::DB::Default;
17
use SL::DB::Unit;
18

  
19
use SL::Helper::DateTime;
20

  
21
use List::Util qw(max first);
22
use List::MoreUtils qw(none pairwise);
23

  
24
use Rose::Object::MakeMethods::Generic
25
(
26
 'scalar --get_set_init' => [ qw(order valid_types type cv p) ],
27
);
28

  
29

  
30
# safety
31
__PACKAGE__->run_before('_check_auth');
32

  
33
__PACKAGE__->run_before('_recalc',
34
                        only => [ qw(edit update save) ]);
35

  
36
__PACKAGE__->run_before('_get_unalterable_data',
37
                        only => [ qw(save save_and_delivery_order create_pdf send_email) ]);
38

  
39
#
40
# actions
41
#
42

  
43
sub action_add {
44
  my ($self) = @_;
45

  
46
  $self->order->transdate(DateTime->now_local());
47

  
48
  $self->_pre_render();
49
  $self->render(
50
    'order/form',
51
    title => $self->type eq _sales_order_type()    ? $::locale->text('Add Sales Order')
52
           : $self->type eq _purchase_order_type() ? $::locale->text('Add Purchase Order')
53
           : '',
54
    %{$self->{template_args}}
55
  );
56
}
57

  
58
sub action_edit {
59
  my ($self) = @_;
60

  
61
  $self->_pre_render();
62
  $self->render(
63
    'order/form',
64
    title => $self->type eq _sales_order_type()    ? $::locale->text('Edit Sales Order')
65
           : $self->type eq _purchase_order_type() ? $::locale->text('Edit Purchase Order')
66
           : '',
67
    %{$self->{template_args}}
68
  );
69
}
70

  
71
sub action_update {
72
  my ($self) = @_;
73

  
74
  $self->_pre_render();
75
  $self->render(
76
    'order/form',
77
    title => $self->type eq _sales_order_type()    ? $::locale->text('Edit Sales Order')
78
           : $self->type eq _purchase_order_type() ? $::locale->text('Edit Purchase Order')
79
           : '',
80
    %{$self->{template_args}}
81
  );
82
}
83

  
84
sub action_save {
85
  my ($self) = @_;
86

  
87
  my $errors = $self->_save();
88

  
89
  if (scalar @{ $errors }) {
90
    $self->js->flash('error', $_) foreach @{ $errors };
91
    return $self->js->render();
92
  }
93

  
94
  flash_later('info', $::locale->text('The order has been saved'));
95
  my @redirect_params = (
96
    action => 'edit',
97
    type   => $self->type,
98
    id     => $self->order->id,
99
  );
100

  
101
  $self->redirect_to(@redirect_params);
102
}
103

  
104
sub action_customer_vendor_changed {
105
  my ($self) = @_;
106

  
107
  my $cv_method = $self->cv;
108

  
109
  if ($self->order->$cv_method->contacts && scalar @{ $self->order->$cv_method->contacts } > 0) {
110
    $self->js->show('#cp_row');
111
  } else {
112
    $self->js->hide('#cp_row');
113
  }
114

  
115
  if ($self->order->$cv_method->shipto && scalar @{ $self->order->$cv_method->shipto } > 0) {
116
    $self->js->show('#shipto_row');
117
  } else {
118
    $self->js->hide('#shipto_row');
119
  }
120

  
121
  $self->js
122
    ->replaceWith('#order_cp_id',     $self->build_contact_select)
123
    ->replaceWith('#order_shipto_id', $self->build_shipto_select)
124
    ->val('#order_taxzone_id', $self->order->taxzone_id)
125
    ->focus('#order_' . $self->cv . '_id')
126
    ->render($self);
127
}
128

  
129
sub action_add_item {
130
  my ($self) = @_;
131

  
132
  my $form_attr = $::form->{add_item};
133

  
134
  return unless $form_attr->{parts_id};
135

  
136
  my $item = SL::DB::OrderItem->new;
137
  $item->assign_attributes(%$form_attr);
138

  
139
  my $part        = SL::DB::Part->new(id => $form_attr->{parts_id})->load;
140
  my $cv_method   = $self->cv;
141
  my $cv_discount = $self->order->$cv_method? $self->order->$cv_method->discount : 0.0;
142

  
143
  my %new_attr;
144
  $new_attr{part}        = $part;
145
  $new_attr{description} = $part->description if ! $item->description;
146
  $new_attr{qty}         = 1.0                if ! $item->qty;
147
  $new_attr{unit}        = $part->unit;
148
  $new_attr{sellprice}   = $part->sellprice   if ! $item->sellprice;
149
  $new_attr{discount}    = $cv_discount       if ! $item->discount;
150

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

  
156
  $item->assign_attributes(%new_attr);
157

  
158
  $self->order->add_items($item);
159

  
160
  $self->_recalc();
161

  
162
  my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
163
  my $row_as_html = $self->p->render('order/tabs/_row', ITEM => $item, ID => $item_id);
164

  
165
  $self->js
166
    ->append('#row_table_id', $row_as_html)
167
    ->val('.add_item_input', '')
168
    ->run('row_table_scroll_down')
169
    ->run('row_set_keyboard_events_by_id', $item_id)
170
    ->on('.recalc', 'change', 'recalc_amounts_and_taxes')
171
    ->focus('#add_item_parts_id_name');
172

  
173
  $self->_js_redisplay_amounts_and_taxes;
174
  $self->js->render();
175
}
176

  
177
sub action_recalc_amounts_and_taxes {
178
  my ($self) = @_;
179

  
180
  $self->_recalc();
181

  
182
  $self->_js_redisplay_linetotals;
183
  $self->_js_redisplay_amounts_and_taxes;
184
  $self->js->render();
185
}
186

  
187
sub _js_redisplay_linetotals {
188
  my ($self) = @_;
189

  
190
  my @data = map {$::form->format_amount(\%::myconfig, $_->{linetotal}, 2, 0)} @{ $self->order->items };
191
  $self->js
192
    ->run('redisplay_linetotals', \@data);
193
}
194

  
195
sub _js_redisplay_amounts_and_taxes {
196
  my ($self) = @_;
197

  
198
  $self->js
199
    ->html('#netamount_id', $::form->format_amount(\%::myconfig, $self->order->netamount, -2))
200
    ->html('#amount_id',    $::form->format_amount(\%::myconfig, $self->order->amount,    -2))
201
    ->remove('.tax_row')
202
    ->insertBefore($self->build_tax_rows, '#amount_row_id');
203
}
204

  
205
#
206
# helpers
207
#
208

  
209
sub init_valid_types {
210
  [ _sales_order_type(), _purchase_order_type() ];
211
}
212

  
213
sub init_type {
214
  my ($self) = @_;
215

  
216
  if (none { $::form->{type} eq $_ } @{$self->valid_types}) {
217
    die "Not a valid type for order";
218
  }
219

  
220
  $self->type($::form->{type});
221
}
222

  
223
sub init_cv {
224
  my ($self) = @_;
225

  
226
  my $cv = $self->type eq _sales_order_type()    ? 'customer'
227
         : $self->type eq _purchase_order_type() ? 'vendor'
228
         : die "Not a valid type for order";
229

  
230
  return $cv;
231
}
232

  
233
sub init_p {
234
  SL::Presenter->get;
235
}
236

  
237
sub init_order {
238
  _make_order();
239
}
240

  
241
sub _check_auth {
242
  my ($self) = @_;
243

  
244
  my $right_for = { map { $_ => $_.'_edit' } @{$self->valid_types} };
245

  
246
  my $right   = $right_for->{ $self->type };
247
  $right    ||= 'DOES_NOT_EXIST';
248

  
249
  $::auth->assert($right);
250
}
251

  
252
sub build_contact_select {
253
  my ($self) = @_;
254

  
255
  $self->p->select_tag('order.cp_id', [ $self->order->{$self->cv}->contacts ],
256
                       value_key  => 'cp_id',
257
                       title_key  => 'full_name_dep',
258
                       default    => $self->order->cp_id,
259
                       with_empty => 1,
260
                       style      => 'width: 300px',
261
  );
262
}
263

  
264
sub build_shipto_select {
265
  my ($self) = @_;
266

  
267
  $self->p->select_tag('order.shipto_id', [ $self->order->{$self->cv}->shipto ],
268
                       value_key  => 'shipto_id',
269
                       title_key  => 'displayable_id',
270
                       default    => $self->order->shipto_id,
271
                       with_empty => 1,
272
                       style      => 'width: 300px',
273
  );
274
}
275

  
276
sub build_tax_rows {
277
  my ($self) = @_;
278

  
279
  my $rows_as_html;
280
  foreach my $tax (sort { $a->{tax}->rate cmp $b->{tax}->rate } @{ $self->{taxes} }) {
281
    $rows_as_html .= $self->p->render('order/tabs/_tax_row', TAX => $tax);
282
  }
283
  return $rows_as_html;
284
}
285

  
286

  
287
sub _make_order {
288
  my ($self) = @_;
289

  
290
  # add_items adds items to an order with no items for saving, but they cannot
291
  # be retrieved via items until the order is saved. Adding empty items to new
292
  # order here solves this problem.
293
  my $order;
294
  $order   = SL::DB::Manager::Order->find_by(id => $::form->{id}) if $::form->{id};
295
  $order ||= SL::DB::Order->new(orderitems => []);
296

  
297
  $order->assign_attributes(%{$::form->{order}});
298

  
299
  return $order;
300
}
301

  
302

  
303
sub _recalc {
304
  my ($self) = @_;
305

  
306
  # bb: todo: currency later
307
  $self->order->currency_id($::instance_conf->get_currency_id());
308

  
309
  my %pat = $self->order->calculate_prices_and_taxes();
310
  $self->{taxes} = [];
311
  foreach my $tax_chart_id (keys %{ $pat{taxes} }) {
312
    my $tax = SL::DB::Manager::Tax->find_by(chart_id => $tax_chart_id);
313
    push(@{ $self->{taxes} }, { amount => $pat{taxes}->{$tax_chart_id},
314
                                tax    => $tax });
315
  }
316

  
317
  pairwise { $a->{linetotal} = $b->{linetotal} } @{$self->order->items}, @{$pat{items}};
318
}
319

  
320

  
321
sub _get_unalterable_data {
322
  my ($self) = @_;
323

  
324
  foreach my $item (@{ $self->order->items }) {
325
    if ($item->id) {
326
      # load data from orderitems (db)
327
      my $db_item = SL::DB::OrderItem->new(id => $item->id)->load;
328
      $item->$_($db_item->$_) for qw(active_discount_source active_price_source longdescription);
329
    } else {
330
      # set data from part (or other sources)
331
      $item->longdescription($item->part->notes);
332
      #$item->active_price_source('');
333
      #$item->active_discount_source('');
334
    }
335

  
336
    # autovivify all cvars that are not in the form (cvars_by_config can do it).
337
    # workaround to pre-parse number-cvars (parse_custom_variable_values does not parse number values).
338
    foreach my $var (@{ $item->cvars_by_config }) {
339
      $var->unparsed_value($::form->parse_amount(\%::myconfig, $var->{__unparsed_value})) if ($var->config->type eq 'number' && exists($var->{__unparsed_value}));
340
    }
341
    $item->parse_custom_variable_values;
342
  }
343
}
344

  
345

  
346
sub _save {
347
  my ($self) = @_;
348

  
349
  my $errors = [];
350
  my $db = $self->order->db;
351

  
352
  $db->do_transaction(
353
    sub {
354
      $self->order->save();
355
  }) || push(@{$errors}, $db->error);
356

  
357
  return $errors;
358
}
359

  
360

  
361
sub _pre_render {
362
  my ($self) = @_;
363

  
364
  $self->{all_taxzones}  = SL::DB::Manager::TaxZone->get_all_sorted();
365
  $self->{all_employees} = SL::DB::Manager::Employee->get_all(where => [ or => [ id => $self->order->employee_id,
366
                                                                                 deleted => 0 ] ],
367
                                                              sort_by => 'name');
368
  $self->{all_salesmen}  = SL::DB::Manager::Employee->get_all(where => [ or => [ id => $self->order->salesman_id,
369
                                                                                 deleted => 0 ] ],
370
                                                              sort_by => 'name');
371
  $self->{all_projects}  = SL::DB::Manager::Project->get_all(where => [ or => [ id => $self->order->globalproject_id,
372
                                                                                active => 1 ] ],
373
                                                             sort_by => 'projectnumber');
374

  
375
  $self->{current_employee_id} = SL::DB::Manager::Employee->current->id;
376
}
377

  
378
sub _sales_order_type {
379
  'sales_order';
380
}
381

  
382
sub _purchase_order_type {
383
  'purchase_order';
384
}
385

  
386
1;
js/locale/de.js
52 52
"Part picker":"Artikelauswahl",
53 53
"Paste":"Einfügen",
54 54
"Paste template":"Vorlage einfügen",
55
"Please select a customer.":"Bitte wählen Sie einen Kunden aus.",
56
"Please select a vendor.":"Bitte wählen Sie einen Lieferanten aus.",
55 57
"Price Types":"Preistypen",
56 58
"Project link actions":"Projektverknüpfungs-Aktionen",
57 59
"Quotations/Orders actions":"Aktionen für Angebote/Aufträge",
locale/de/all
2019 2019
  'Please re-run the analysis for broken general ledger entries by clicking this button:' => 'Bitte wiederholen Sie die Analyse der Hauptbucheinträge, indem Sie auf diesen Button klicken:',
2020 2020
  'Please read the file'        => 'Bitte lesen Sie die Datei',
2021 2021
  'Please select a customer from the list below.' => 'Bitte einen Endkunden aus der Liste auswählen',
2022
  'Please select a customer.'   => 'Bitte wählen Sie einen Kunden aus.',
2022 2023
  'Please select a part from the list below.' => 'Bitte wählen Sie einen Artikel aus der Liste aus.',
2023 2024
  'Please select a vendor from the list below.' => 'Bitte einen Händler aus der Liste auswählen',
2025
  'Please select a vendor.'     => 'Bitte wählen Sie einen Lieferanten aus.',
2024 2026
  'Please select the dataset you want to delete:' => 'Bitte wählen Sie die zu löschende Datenbank aus:',
2025 2027
  'Please select the destination bank account for the collections:' => 'Bitte wählen Sie das Bankkonto als Ziel für die Einzüge aus:',
2026 2028
  'Please select the source bank account for the transfers:' => 'Bitte wählen Sie das Bankkonto als Quelle für die Überweisungen aus:',
......
2837 2839
  'The number of days for full payment' => 'Die Anzahl Tage, bis die Rechnung in voller Höhe bezahlt werden muss',
2838 2840
  'The numbering will start at 1 with each requirement spec.' => 'Die Nummerierung beginnt bei jedem Pflichtenheft bei 1.',
2839 2841
  'The option field is empty.'  => 'Das Optionsfeld ist leer.',
2842
  'The order has been saved'    => 'Der Auftrag wurde gespeichert.',
2840 2843
  'The package name is invalid.' => 'Der Paketname ist ungültig.',
2841 2844
  'The parts for this delivery order have already been transferred in.' => 'Die Artikel dieses Lieferscheins wurden bereits eingelagert.',
2842 2845
  'The parts for this delivery order have already been transferred out.' => 'Die Artikel dieses Lieferscheins wurden bereits ausgelagert.',
......
3390 3393
  'dated'                       => 'datiert',
3391 3394
  'debug'                       => 'Debug',
3392 3395
  'delete'                      => 'Löschen',
3396
  'delete item'                 => 'Position löschen',
3393 3397
  'delivered'                   => 'geliefert',
3394 3398
  'deliverydate'                => 'Lieferdatum',
3395 3399
  'difference as skonto'        => 'Differenz als Skonto',
templates/webpages/order/form.html
1
[%- USE T8 %]
2
[%- USE LxERP %]
3
[%- USE L %]
4

  
5
<form method="post" action="controller.pl" id="order_form">
6
  <div class="listtop">[% FORM.title %]</div>
7

  
8
  [% L.hidden_tag('callback', FORM.callback) %]
9
  [% L.hidden_tag('type',     FORM.type) %]
10
  [% L.hidden_tag('id',       SELF.order.id) %]
11

  
12
  [%- INCLUDE 'common/flash.html' %]
13

  
14
  <div class="tabwidget" id="order_tabs">
15
    <ul>
16
      <li><a href="#ui-tabs-basic-data">[% 'Basic Data' | $T8 %]</a></li>
17
[%- IF INSTANCE_CONF.get_webdav %]
18
      <li><a href="#ui-tabs-webdav">[% 'WebDAV' | $T8 %]</a></li>
19
[%- END %]
20
    </ul>
21

  
22
    [% PROCESS "order/tabs/basic_data.html" %]
23
    [% PROCESS 'webdav/_list.html' %]
24
    <div id="ui-tabs-1">
25
      [%- LxERP.t8("Loading...") %]
26
    </div>
27
  </div>
28

  
29
  <br>
30

  
31
  [% L.hidden_tag('action', 'Order/dispatch') %]
32

  
33
  [% L.button_tag('save()', LxERP.t8('Save')) %]
34

  
35
</form>
36

  
37

  
38
<script type='text/javascript'>
39

  
40
function save() {
41
  if (!check_cv()) return;
42
  var data = $('#order_form').serialize();
43
  data += '&action=Order/save';
44

  
45
  $.post("controller.pl", data, kivi.eval_json_result);
46
}
47

  
48
function check_cv() {
49
  if ($('#order_[%- cv_id %]').val() == '') {
50
    [%- IF SELF.cv == 'customer' %]
51
      alert(kivi.t8('Please select a customer.'));
52
    [%- ELSE %]
53
      alert(kivi.t8('Please select a vendor.'));
54
    [%- END %]
55
    return false;
56
  }
57
  return true;
58
}
59
</script>
templates/webpages/order/tabs/_item_input.html
1
[%- USE T8 %][%- USE HTML %][%- USE LxERP %][%- USE L %]
2

  
3
 <div>
4
  <table id="input_row_table_id">
5
    <thead>
6
      <tr class="listheading">
7
        <th class="listheading" nowrap >[%- 'Part'         | $T8 %] </th>
8
        <th class="listheading" nowrap >[%- 'Description'  | $T8 %] </th>
9
        <th class="listheading" nowrap width="5" >[%- 'Qty'          | $T8 %] </th>
10
        <th class="listheading" nowrap width="15">[%- 'Price'        | $T8 %] </th>
11
        <th class="listheading" nowrap width="5" >[%- 'Discount'     | $T8 %] </th>
12
        <th></th>
13
      </tr>
14
    </thead>
15
    <tbody>
16
      <tr valign="top" class="listrow">
17
        <td>[% L.part_picker('add_item.parts_id', '', fat_set_item=1, style='width: 300px', class="add_item_input") %]</td>
18
        <td>[% L.input_tag('add_item.description', '', class="add_item_input") %]</td>
19
        <td>[% L.input_tag('add_item.qty_as_number', '', size = 5, style='text-align:right', class="add_item_input") %]</td>
20
        <td>[% L.input_tag('add_item.sellprice_as_number', '', size = 10, style='text-align:right', class="add_item_input") %]</td>
21
        <td>[% L.input_tag('add_item.discount_as_percent', '', size = 5, style='text-align:right', class="add_item_input") %]</td>
22
        <td>[% L.button_tag('add_item()', LxERP.t8('Add part')) %]</td>
23
      </tr>
24
    </tbody>
25
  </table>
26
 </div>
templates/webpages/order/tabs/_row.html
1
[%- USE T8 %]
2
[%- USE HTML %]
3
[%- USE LxERP %]
4
[%- USE L %]
5

  
6
<tbody class="row_entry">
7

  
8
  <tr class="listrow0">
9
    <td style='display:none'>
10
      [% L.hidden_tag("order.orderitems[+].id", ITEM.id, id='item_' _ ID) %]
11
      [% L.hidden_tag("order.orderitems[].parts_id", ITEM.parts_id) %]
12
    </td>
13
    <td align="center">
14
      <img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]" class="dragdrop">
15
    </td>
16
    <td align="center">
17
      [%- L.button_tag("delete_order_item_row(this)",
18
                       LxERP.t8("X"),
19
                       confirm=LxERP.t8("Are you sure?")) %]
20
    </td>
21
    <td>
22
      [% HTML.escape(ITEM.part.partnumber) %]
23
    </td>
24
    <td>
25
      [% L.input_tag("order.orderitems[].description",
26
                     ITEM.description,
27
                     style='width: 300px') %]
28
    </td>
29
    <td>
30
      [%- L.input_tag("order.orderitems[].qty_as_number",
31
                      ITEM.qty_as_number,
32
                      size = 5,
33
                      style='text-align:right',
34
                      class="recalc") %]
35
    </td>
36
    <td>
37
      [%- L.input_tag("order.orderitems[].price_factor",
38
                      ITEM.price_factor,
39
                      size = 5,
40
                      style='text-align:right',
41
                      class="recalc") %]
42
    </td>
43
    <td nowrap>
44
      [%- L.input_tag("order.orderitems[].unit",
45
                      ITEM.unit,
46
                      size = 5,
47
                      class="recalc") %]
48
    </td>
49
    <td>
50
      [%- L.input_tag("order.orderitems[].sellprice_as_number",
51
                      ITEM.sellprice_as_number,
52
                      size = 10,
53
                      style='text-align:right',
54
                      class="recalc") %]
55
    </td>
56
    <td>
57
      [%- L.input_tag("order.orderitems[].discount_as_percent",
58
                      ITEM.discount_as_percent,
59
                      size = 5,
60
                      style='text-align:right',
61
                      class="recalc") %]
62
    </td>
63
    <td align="right">
64
      [%- L.div_tag(LxERP.format_amount(ITEM.linetotal, 2, 0), name="linetotal") %]
65
    </td>
66

  
67
  </tr>
68

  
69
  <tr class="listrow1" style="display:none">
70
    <td colspan="100%">
71
      <table>
72
        <tr class="listrow1">
73
          [%- SET n = 0 %]
74
          [%- FOREACH var = ITEM.cvars_by_config %]
75
            [%- NEXT UNLESS (var.config.processed_flags.editable && ITEM.part.cvar_by_name(var.config.name).is_valid) %]
76
            [%- SET n = n + 1 %]
77
            <th>
78
              [% var.config.description %]
79
            </th>
80
            <td>
81
              [% L.hidden_tag('order.orderitems[].custom_variables[+].config_id', var.config.id) %]
82
              [% L.hidden_tag('order.orderitems[].custom_variables[].id', var.id) %]
83
              [% L.hidden_tag('order.orderitems[].custom_variables[].sub_module', var.sub_module) %]
84
              [% INCLUDE 'common/render_cvar_input.html' var_name='order.orderitems[].custom_variables[].unparsed_value' %]
85
            </td>
86
            [%- IF (n % (MYCONFIG.form_cvars_nr_cols || 3)) == 0 %]
87
              </tr><tr class="listrow1">
88
            [%- END %]
89
          [%- END %]
90
        </tr>
91
      </table>
92
    </td>
93
  </tr>
94

  
95
</tbody>
templates/webpages/order/tabs/_tax_row.html
1
[%- USE T8 %]
2
[%- USE HTML %]
3
[%- USE LxERP %]
4
[%- USE L %]
5

  
6
<tr class="tax_row">
7
  <th align="right">[%- TAX.tax.taxdescription %] [% TAX.tax.rate_as_percent %]%</th>
8
  <td align="right">[%- LxERP.format_amount(TAX.amount, 2, 0) %]</td>
9
</tr>
templates/webpages/order/tabs/basic_data.html
1
[%- USE T8 %]
2
[%- USE HTML %]
3
[%- USE LxERP %]
4
[%- USE L %]
5

  
6
<div id="ui-tabs-basic-data">
7
  <table width="100%">
8
    <tr valign="top">
9
      <td>
10
        <table width="100%">
11
          <tr>
12
            <th align="right">[% SELF.cv | $T8 %]</th>
13
            [% SET cv_id = SELF.cv _ '_id' %]
14
            <td>[% L.customer_vendor_picker("order.${SELF.cv}" _ '_id', SELF.order.$cv_id, type=SELF.cv, style='width: 300px') %]</td>
15
          </tr>
16

  
17
          <tr id='cp_row' [%- IF !SELF.order.${SELF.cv}.contacts.size %]style='display:none'[%- END %]>
18
            <th align="right">[% 'Contact Person' | $T8 %]</th>
19
            <td>[% L.select_tag('order.cp_id',
20
                                SELF.order.${SELF.cv}.contacts,
21
                                default=SELF.order.cp_id,
22
                                title_key='full_name_dep',
23
                                value_key='cp_id',
24
                                with_empty=1,
25
                                style='width: 300px') %]</td>
26
          </tr>
27

  
28
          <tr id='shipto_row' [%- IF !SELF.order.${SELF.cv}.shipto.size %]style='display:none'[%- END %]>
29
            <th align="right">[% 'Shipping Address' | $T8 %]</th>
30
            <td>[% L.select_tag('order.shipto_id',
31
                                SELF.order.${SELF.cv}.shipto,
32
                                default=SELF.order.shipto_id,
33
                                title_key='displayable_id',
34
                                value_key='shipto_id',
35
                                with_empty=1,
36
                                style='width: 300px') %]</td>
37
          </tr>
38

  
39
          <tr>
40
            <th align="right">[% 'Steuersatz' | $T8 %]</th>
41
            <td>[% L.select_tag('order.taxzone_id', SELF.all_taxzones, default=SELF.order.taxzone_id, title_key='description', style='width: 300px') %]</td>
42
          </tr>
43

  
44
          <tr>
45
            <th align="right">[% 'Shipping Point' | $T8 %]</th>
46
            <td>[% L.input_tag('order.shippingpoint', SELF.order.shippingpoint, style='width: 300px') %]</td>
47
          </tr>
48

  
49
          <tr>
50
            <th align="right">[% 'Ship via' | $T8 %]</th>
51
            <td>[% L.input_tag('order.shipvia', SELF.order.shipvia, style='width: 300px') %]</td>
52
          </tr>
53

  
54
          <tr>
55
            <th align="right">[% 'Transaction description' | $T8 %]</th>
56
            <td>[% L.input_tag('order.transaction_description', SELF.order.transaction_description, style='width: 300px') %]</td>
57
          </tr>
58

  
59
        </table>
60
      </td>
61

  
62
      <td align="right">
63
        <table>
64

  
65
          <tr>
66
            <td colspan="2" align="center">
67
              [%- IF SELF.order.id %]
68
                <label for="order.delivered">[% 'Delivery Order(s) for full qty created' | $T8 %]</label>
69
                [% L.yes_no_tag('order.delivered', SELF.order.delivered) %]
70
                <label for="order.closed">[% 'Closed' | $T8 %]</label>
71
                [% L.yes_no_tag('order.closed', SELF.order.closed) %]
72
              [%- END %]
73
            </td>
74
          </tr>
75

  
76
          <tr>
77
            <th align="right">[% 'Employee' | $T8 %]</th>
78
            <td>[% L.select_tag('order.employee_id',
79
              SELF.all_employees,
80
              default=(SELF.order.employee_id ? SELF.order.employee_id : SELF.current_employee_id),
81
              title_key='safe_name') %]</td>
82
          </tr>
83

  
84
          [% IF SELF.cv == 'customer' %]
85
          <tr>
86
            <th align="right">[% 'Salesman' | $T8 %]</th>
87
            <td>[% L.select_tag('order.salesman_id',
88
              SELF.all_salesmen,
89
              default=(SELF.order.salesman_id ? SELF.order.salesman_id : SELF.current_employee_id),
90
              title_key='safe_name') %]</td>
91
          </tr>
92
          [% END %]
93

  
94
          <tr>
95
            <th width="70%" align="right" nowrap>[% 'Order Number' | $T8 %]</th>
96
            <td>[% L.input_tag('order.ordnumber', SELF.order.ordnumber, size = 11) %]</td>
97
          </tr>
98

  
99
          <tr>
100
            <th width="70%" align="right" nowrap>[% 'Customer Order Number' | $T8 %]</th>
101
            <td>[% L.input_tag('order.cusordnumber', SELF.order.cusordnumber, size = 11) %]</td>
102
          </tr>
103

  
104
          <tr>
105
            <th width="70%" align="right" nowrap>[% 'Order Date' | $T8 %]</th>
106
            <td>[% L.date_tag('order.transdate', SELF.order.transdate) %]</td>
107
          </tr>
108

  
109
          <tr>
110
            <th width="70%" align="right" nowrap>[% 'Project Number' | $T8 %]</th>
111
            <td>[%- L.select_tag('order.globalproject_id', SELF.all_projects, default=SELF.order.globalproject_id, title_key='projectnumber', with_empty = 1) %]</td>
112
          </tr>
113

  
114
        </table>
115

  
116
      </td>
117
    </tr>
118
  </table>
119

  
120
  [%- PROCESS order/tabs/_item_input.html %]
121

  
122
  <table width="100%">
123
    <tr>
124
      <td>
125

  
126
        <div id="row_table_scroll_id" style="overflow-y: auto; height: 25vh">
127
          <table id="row_table_id" width="100%">
128
            <thead>
129
              <tr class="listheading">
130
                <th class="listheading" style='display:none'></th>
131
                <th class="listheading" style='text-align:center' nowrap width="1"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></th>
132
                <th class="listheading" style='text-align:center' nowrap width="1"><img src="image/close.png" alt="[%- LxERP.t8('delete item') %]"></th>
133
                <th class="listheading" nowrap width="15">[%- 'Partnumber'   | $T8 %] </th>
134
                <th class="listheading" nowrap           >[%- 'Description'  | $T8 %] </th>
135
                <th class="listheading" nowrap width="5" >[%- 'Qty'          | $T8 %] </th>
136
                <th class="listheading" nowrap width="5" >[%- 'Price Factor' | $T8 %] </th>
137
                <th class="listheading" nowrap width="5" >[%- 'Unit'         | $T8 %] </th>
138
                <th class="listheading" nowrap width="15">[%- 'Price'        | $T8 %] </th>
139
                <th class="listheading" nowrap width="5" >[%- 'Discount'     | $T8 %] </th>
140
                <th class="listheading" nowrap width="10">[%- 'Extended'     | $T8 %] </th>
141
              </tr>
142
            </thead>
143

  
144
            [%- FOREACH item = SELF.order.items_sorted %]
145
              [%- PROCESS order/tabs/_row.html ITEM=item %]
146
            [%- END %]
147

  
148
          </table>
149
        </div>
150

  
151
      </td>
152
    </tr>
153

  
154
    <tr>
155
    </tr>
156

  
157
    <tr>
158
      <td align="right">
159
        <table>
160
          [%- IF NOT taxincluded %]
161
          <tr>
162
            <th align="right">[%- 'Subtotal' | $T8 %]</th>
163
            <td align="right">
164
              [%- L.div_tag(SELF.order.netamount_as_number, id='netamount_id') %]
165
            </td>
166
          </tr>
167
          [%- END %]
168
          [%- FOREACH tax = SELF.taxes %]
169
            [%- PROCESS order/tabs/_tax_row.html TAX=tax %]
170
          [%- END %]
171
          <tr id="amount_row_id">
172
            <th align="right">[%- 'Total' | $T8 %]</th>
173
            <td align="right">
174
              <table>
175
                [%- IF NOT taxincluded %]
176
                <tr>
177
                  <th align="right">[%- 'Subtotal' | $T8 %]</th>
178
                  <td align="right">
179
                    [%- L.div_tag(SELF.order.netamount_as_number, id='netamount_id') %]
180
                  </td>
181
                </tr>
182
                [%- END %]
183
                [%- FOREACH tax = SELF.taxes %]
184
                  [%- PROCESS order/tabs/_tax_row.html TAX=tax %]
185
                [%- END %]
186
                <tr id="amount_row_id">
187
                  <th align="right">[%- 'Total' | $T8 %]</th>
188
                  <td align="right">
189
                    [%- L.div_tag(SELF.order.amount_as_number, id='amount_id') %]
190
                  </td>
191
                </tr>
192
              </table>
193
            </td>
194

  
195
          </tr>
196
        </table>
197
      </td>
198
    </tr>
199

  
200
  </table>
201

  
202
</div>
203

  
204

  
205
[% L.sortable_element('#row_table_id') %]
206

  
207
<script type='text/javascript'>
208
function reload_cv_dependend_selections() {
209
  $.post("controller.pl", { 'action': 'Order/customer_vendor_changed',
210
                            'cv_id':  function(){ return $('#order_[%- cv_id%]').val() },
211
                            'type':   function(){ return $('#type').val() },
212
                          }, kivi.eval_json_result);
213
}
214

  
215
function add_item() {
216
  if ($('#add_item_parts_id').val() == '') return;
217
  if (!check_cv()) return;
218

  
219
  var data = $('#order_form').serialize();
220
  data += '&action=Order/add_item';
221

  
222
  $.post("controller.pl", data, kivi.eval_json_result);
223
}
224

  
225
function delete_order_item_row(clicked) {
226
  var row = $(clicked).parents("tbody").first();
227
  $(row).remove();
228

  
229
  recalc_amounts_and_taxes();
230
}
231

  
232
function recalc_amounts_and_taxes() {
233
  var data = $('#order_form').serialize();
234
  data += '&action=Order/recalc_amounts_and_taxes';
235

  
236
  $.post("controller.pl", data, kivi.eval_json_result);
237
}
238

  
239
function redisplay_linetotals(data) {
240
  $('.row_entry [name="linetotal"]').each(function(idx, elt) {
241
    $(elt).html(data[idx]);
242
  });
243
}
244

  
245
function row_table_scroll_down() {
246
  $('#row_table_scroll_id').scrollTop($('#row_table_scroll_id')[0].scrollHeight);
247
}
248

  
249
function row_set_keyboard_events_by_id(item_id) {
250
  var row = $('#item_' + item_id).parents("tbody").first();
251

  
252
  row_set_keyboard_events(row);
253
}
254

  
255
function row_set_keyboard_events(rows) {
256
  $(rows).keydown(function(event) {
257
    if(event.keyCode == 40 && event.shiftKey == true) {
258
      // shift arrow down
259
      event.preventDefault();
260
      var row = $(event.target).parents(".row_entry").first();
261
      $(row).children().not(':first').show();
262
      return false;
263
    }
264
    if(event.keyCode == 38 && event.shiftKey == true) {
265
      // shift arrow up
266
      event.preventDefault();
267
      var row = $(event.target).parents(".row_entry").first();
268
      $(row).children().not(':first').hide();
269
      return false;
270
    }
271
  });
272

  
273
  $(rows).dblclick(function(event) {
274
      event.preventDefault();
275
      var row = $(event.target).parents(".row_entry").first();
276
      $(row).children().not(':first').toggle();
277
      return false;
278
  });
279
}
280

  
281
$(function(){
282
  $('#order_[%- cv_id %]').change(reload_cv_dependend_selections);
283
  $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
284
  $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) });
285
  $('.add_item_input').keydown(function(event) {
286
    if(event.keyCode == 13) {
287
      event.preventDefault();
288
      add_item();
289
      return false;
290
    }
291
  });
292
  row_set_keyboard_events($('.row_entry'));
293
  $('.recalc').change(recalc_amounts_and_taxes);
294
});
295

  
296
</script>

Auch abrufbar als: Unified diff