Auftrags-Controller: neuen Artikel aus Maske heraus anlegen können
authorBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 25 Sep 2019 14:36:24 +0000 (16:36 +0200)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 23 Jun 2021 11:21:42 +0000 (13:21 +0200)
SL/Controller/Order.pm
SL/Controller/Part.pm
doc/changelog
js/kivi.Order.js
locale/de/all
locale/en/all
templates/webpages/order/tabs/_item_input.html

index fe27d55..70f75aa 100644 (file)
@@ -777,6 +777,8 @@ sub action_unit_changed {
 sub action_add_item {
   my ($self) = @_;
 
+  delete $::form->{add_item}->{create_part_type};
+
   my $form_attr = $::form->{add_item};
 
   return unless $form_attr->{parts_id};
@@ -976,6 +978,62 @@ sub action_price_popup {
   $self->render_price_dialog($item);
 }
 
+# save the order in a session variable and redirect to the part controller
+sub action_create_part {
+  my ($self) = @_;
+
+  $::lxdebug->dump(0, "bb: form", $::form);
+  my $previousform = $::auth->save_form_in_session(non_scalars => 1);
+
+  my $callback     = $self->url_for(
+    action       => 'return_from_create_part',
+    type         => $self->type, # type is needed for check_auth on return
+    previousform => $previousform,
+  );
+
+  flash_later('info', t8('You are adding a new part while you are editing another document. You will be redirected to your document when saving the new part or aborting this form.'));
+
+  my @redirect_params = (
+    controller => 'Part',
+    action     => 'add',
+    part_type  => $::form->{add_item}->{create_part_type},
+    callback   => $callback,
+    show_abort => 1,
+  );
+
+  $self->redirect_to(@redirect_params);
+}
+
+sub action_return_from_create_part {
+  my ($self) = @_;
+
+  $self->{created_part} = SL::DB::Part->new(id => delete $::form->{new_parts_id})->load if $::form->{new_parts_id};
+
+  $::auth->restore_form_from_session(delete $::form->{previousform});
+
+  # set item ids to new fake id, to identify them as new items
+  foreach my $item (@{$self->order->items_sorted}) {
+    $item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
+  }
+
+  $self->recalc();
+  $self->get_unalterable_data();
+  $self->pre_render();
+
+  # trigger rendering values for second row/longdescription as hidden,
+  # because they are loaded only on demand. So we need to keep the values
+  # from the source.
+  $_->{render_second_row}      = 1 for @{ $self->order->items_sorted };
+  $_->{render_longdescription} = 1 for @{ $self->order->items_sorted };
+
+  $self->render(
+    'order/form',
+    title => $self->get_title_for('edit'),
+    %{$self->{template_args}}
+  );
+
+}
+
 # load the second row for one or more items
 #
 # This action gets the html code for all items second rows by rendering a template for
index 14be0ed..3f7409e 100644 (file)
@@ -157,6 +157,14 @@ sub action_save {
   }
 }
 
+sub action_abort {
+  my ($self) = @_;
+
+  if ( $::form->{callback} ) {
+    $self->redirect_to($::form->unescape($::form->{callback}));
+  }
+}
+
 sub action_delete {
   my ($self) = @_;
 
@@ -1334,6 +1342,12 @@ sub _setup_form_action_bar {
         ],
       ], # end of combobox "Save"
 
+      action => [
+        t8('Abort'),
+        submit   => [ '#ic', { action => "Part/abort" } ],
+        only_if  => !!$::form->{show_abort},
+      ],
+
       action => [
         t8('Delete'),
         call     => [ 'kivi.Part.delete' ],
index dbae02a..5d86a35 100644 (file)
@@ -34,6 +34,8 @@ Mittelgroße neue Features:
    - Anzeige der Mails im Mahnbericht
    - DB-Trigger zum Löschen von Verknüpfungen beim Löschen einer
      Mahnung
+ - Neuer Order-Controller: Artikel können während der Erfassung eines
+   Angebots bzw. Auftrags erfasst werden.
 
 Kleinere neue Features und Detailverbesserungen:
   - Der Status geliefert bei Aufträgen kann mit oder ohne Dienstleistungen
index 5459c0b..a96f49f 100644 (file)
@@ -837,6 +837,13 @@ namespace('kivi.Order', function(ns) {
     follow_up_window();
   };
 
+  ns.create_part = function() {
+    var data = $('#order_form').serializeArray();
+    data.push({ name: 'action', value: 'Order/create_part' });
+
+    $.post("controller.pl", data, kivi.eval_json_result);
+  };
+
 });
 
 $(function() {
index eb78f3e..fb659b3 100755 (executable)
@@ -29,6 +29,7 @@ $self->{texts} = {
   '%'                           => '%',
   '(recommended) Insert the used currencies in the system. You can simply change the name of the currencies by editing the textfields above. Do not use a name of a currency that is already in use.' => '(empfohlen) Fügen Sie die verwaisten Währungen in Ihr System ein. Sie können den Namen der Währung einfach ändern, indem Sie die Felder oben bearbeiten. Benutzen Sie keine Namen von Währungen, die Sie bereits benutzen.',
   '*/'                          => '*/',
+  '+'                           => '+',
   ', if set'                    => ', falls gesetzt',
   '---please select---'         => '---bitte auswählen---',
   '. Automatically generated.'  => '. Automatisch erzeugt.',
@@ -746,6 +747,7 @@ $self->{texts} = {
   'Create a new client'         => 'Einen neuen Mandanten anlegen',
   'Create a new delivery term'  => 'Neue Lieferbedingungen anlegen',
   'Create a new group'          => 'Neue Benutzergruppe erfassen',
+  'Create a new part'           => 'Einen neuen Artikel anlegen',
   'Create a new payment term'   => 'Neue Zahlungsbedingungen anlegen',
   'Create a new price rule'     => 'Neue Preisregel anlegen',
   'Create a new printer'        => 'Einen neuen Drucker anlegen',
@@ -4129,6 +4131,7 @@ $self->{texts} = {
   'Yes'                         => 'Ja',
   'Yes, included by default'    => 'Ja, standardmäßig an',
   'Yes/No (Checkbox)'           => 'Ja/Nein (Checkbox)',
+  'You are adding a new part while you are editing another document. You will be redirected to your document when saving the new part or aborting this form.' => 'Sie legen einen neuen Artikel an, während Sie ein anderes Dokument bearbeiten. Sie werden zu Ihrem Dokument zurückgeleitet, wenn Sie den Artikel speichern oder die Bearbeitung dieser Maske abbrechen.',
   'You are logged out!'         => 'Auf Wiedersehen!',
   'You can also delete this transaction and re-enter it manually.' => 'Alternativ können Sie die Buchung auch mit löschen lassen und sie anschließend neu eingeben.',
   'You can choose account categories for taxes. Depending on these categories taxes will be displayed for transfers in the general ledger or not.' => 'Sie können Kontoarten für Steuern auswählen. Abhängig von diesen Kontoarten werden dann Steuern bei Dialogbuchungen angezeigt oder nicht.',
index 091e70d..c919a7f 100644 (file)
@@ -29,6 +29,7 @@ $self->{texts} = {
   '%'                           => '',
   '(recommended) Insert the used currencies in the system. You can simply change the name of the currencies by editing the textfields above. Do not use a name of a currency that is already in use.' => '',
   '*/'                          => '',
+  '+'                           => '',
   ', if set'                    => '',
   '---please select---'         => '',
   '. Automatically generated.'  => '',
@@ -746,6 +747,7 @@ $self->{texts} = {
   'Create a new client'         => '',
   'Create a new delivery term'  => '',
   'Create a new group'          => '',
+  'Create a new part'           => '',
   'Create a new payment term'   => '',
   'Create a new price rule'     => '',
   'Create a new printer'        => '',
@@ -4128,6 +4130,7 @@ $self->{texts} = {
   'Yes'                         => '',
   'Yes, included by default'    => '',
   'Yes/No (Checkbox)'           => '',
+  'You are adding a new part while you are editing another document. You will be redirected to your document when saving the new part or aborting this form.' => '',
   'You are logged out!'         => '',
   'You can also delete this transaction and re-enter it manually.' => '',
   'You can choose account categories for taxes. Depending on these categories taxes will be displayed for transfers in the general ledger or not.' => '',
index 62f5ccf..1b1bf60 100644 (file)
@@ -4,6 +4,7 @@
   <table id="input_row_table_id">
     <thead>
       <tr class="listheading">
+        <th class="listheading" nowrap >[%- '+'            | $T8 %] </th>
         <th class="listheading" nowrap >[%- 'position'     | $T8 %] </th>
         <th class="listheading" nowrap >[%- 'Part'         | $T8 %] </th>
         <th class="listheading" nowrap >[%- 'Description'  | $T8 %] </th>
     </thead>
     <tbody>
       <tr valign="top" class="listrow">
+        <td class="tooltipster-html" title="[%- 'Create a new part' | $T8 -%]">
+          [% SET type_options = [[ 'part', LxERP.t8('Part') ], [ 'assembly', LxERP.t8('Assembly') ], [ 'service', LxERP.t8('Service') ] ] %]
+          [%- IF INSTANCE_CONF.get_feature_experimental_assortment %]
+            [%- type_options.push([ 'assortment', LxERP.t8('Assortment')]) %]
+          [%- END %]
+          [% L.select_tag('add_item.create_part_type', type_options) %]
+          [% L.button_tag('kivi.Order.create_part()', LxERP.t8('+')) %]
+        </td>
         <td>[% L.input_tag('add_item.position', '', size = 5, class="add_item_input numeric") %]</td>
         <td>
           [%- SET PARAM_KEY = SELF.cv == "customer" ? 'with_customer_partnumber' : 'with_makemodel' -%]
           [%- SET PARAM_VAL = SELF.search_cvpartnumber -%]
-          [% P.part.picker('add_item.parts_id', '', style='width: 300px', class="add_item_input",
+          [% P.part.picker('add_item.parts_id', SELF.created_part, style='width: 300px', class="add_item_input",
                             fat_set_item=1,
                             multiple_pos_input=1,
                             action={set_multi_items='kivi.Order.add_multi_items'},
                             classification_id=SELF.part_picker_classification_ids.as_list.join(','),
                             $PARAM_KEY=PARAM_VAL) %]</td>
-        <td>[% L.input_tag('add_item.description', '', class="add_item_input") %]</td>
+        <td>[% L.input_tag('add_item.description', SELF.created_part.description, class="add_item_input") %]</td>
         <td>
           [% L.input_tag('add_item.qty_as_number', '', size = 5, class="add_item_input numeric") %]
-          [% L.hidden_tag('add_item.unit', '', class="add_item_input") %]
+          [% L.hidden_tag('add_item.unit', SELF.created_part.unit, class="add_item_input") %]
         </td>
-        <td>[% L.input_tag('add_item.sellprice_as_number', '', size = 10, class="add_item_input numeric") %]</td>
+        [%- SET price = LxERP.format_amount(((SELF.type == 'sales_quotation' || SELF.type == 'sales_order') ? SELF.created_part.sellprice : SELF.created_part.lastcost), -2) -%]
+        <td>[% L.input_tag('add_item.sellprice_as_number', price, size = 10, class="add_item_input numeric") %]</td>
         <td>[% L.input_tag('add_item.discount_as_percent', '', size = 5, class="add_item_input numeric") %]</td>
         <td>[% L.button_tag('kivi.Order.add_item()', LxERP.t8('Add part')) %]</td>
       </tr>