Auftrags-Controller: auch für Angebote/Anfragen
authorBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 31 Jan 2018 14:09:49 +0000 (15:09 +0100)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 7 Feb 2018 13:52:45 +0000 (14:52 +0100)
SL/Controller/Order.pm
bin/mozilla/oe.pl
js/kivi.Order.js
menus/user/10-order-controller.yaml
templates/webpages/order/tabs/_second_row.html
templates/webpages/order/tabs/basic_data.html

index ac619d5..4345f66 100644 (file)
@@ -60,8 +60,10 @@ sub action_add {
   $self->_pre_render();
   $self->render(
     'order/form',
-    title => $self->type eq _sales_order_type()    ? $::locale->text('Add Sales Order')
-           : $self->type eq _purchase_order_type() ? $::locale->text('Add Purchase Order')
+    title => $self->type eq _sales_order_type()       ? $::locale->text('Add Sales Order')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('Add Purchase Order')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('Add Quotation')
+           : $self->type eq _request_quotation_type() ? $::locale->text('Add Request for Quotation')
            : '',
     %{$self->{template_args}}
   );
@@ -76,8 +78,10 @@ sub action_edit {
   $self->_pre_render();
   $self->render(
     'order/form',
-    title => $self->type eq _sales_order_type()    ? $::locale->text('Edit Sales Order')
-           : $self->type eq _purchase_order_type() ? $::locale->text('Edit Purchase Order')
+    title => $self->type eq _sales_order_type()       ? $::locale->text('Edit Sales Order')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('Edit Purchase Order')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('Edit Quotation')
+           : $self->type eq _request_quotation_type() ? $::locale->text('Edit Request for Quotation')
            : '',
     %{$self->{template_args}}
   );
@@ -94,7 +98,13 @@ sub action_delete {
     return $self->js->render();
   }
 
-  flash_later('info', $::locale->text('The order has been deleted'));
+  my $text = $self->type eq _sales_order_type()       ? $::locale->text('The order has been deleted')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('The order has been deleted')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('The quotation has been deleted')
+           : $self->type eq _request_quotation_type() ? $::locale->text('The rfq has been deleted')
+           : '';
+  flash_later('info', $text);
+
   my @redirect_params = (
     action => 'add',
     type   => $self->type,
@@ -114,7 +124,13 @@ sub action_save {
     return $self->js->render();
   }
 
-  flash_later('info', $::locale->text('The order has been saved'));
+  my $text = $self->type eq _sales_order_type()       ? $::locale->text('The order has been saved')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('The order has been saved')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('The quotation has been saved')
+           : $self->type eq _request_quotation_type() ? $::locale->text('The rfq has been saved')
+           : '';
+  flash_later('info', $text);
+
   my @redirect_params = (
     action => 'edit',
     type   => $self->type,
@@ -458,7 +474,13 @@ sub action_save_and_delivery_order {
     $self->js->flash('error', $_) foreach @{ $errors };
     return $self->js->render();
   }
-  flash_later('info', $::locale->text('The order has been saved'));
+
+  my $text = $self->type eq _sales_order_type()       ? $::locale->text('The order has been saved')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('The order has been saved')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('The quotation has been saved')
+           : $self->type eq _request_quotation_type() ? $::locale->text('The rfq has been saved')
+           : '';
+  flash_later('info', $text);
 
   my @redirect_params = (
     controller => 'oe.pl',
@@ -480,7 +502,13 @@ sub action_save_and_invoice {
     $self->js->flash('error', $_) foreach @{ $errors };
     return $self->js->render();
   }
-  flash_later('info', $::locale->text('The order has been saved'));
+
+  my $text = $self->type eq _sales_order_type()       ? $::locale->text('The order has been saved')
+           : $self->type eq _purchase_order_type()    ? $::locale->text('The order has been saved')
+           : $self->type eq _sales_quotation_type()   ? $::locale->text('The quotation has been saved')
+           : $self->type eq _request_quotation_type() ? $::locale->text('The rfq has been saved')
+           : '';
+  flash_later('info', $text);
 
   my @redirect_params = (
     controller => 'oe.pl',
@@ -856,7 +884,7 @@ sub _js_redisplay_amounts_and_taxes {
 #
 
 sub init_valid_types {
-  [ _sales_order_type(), _purchase_order_type() ];
+  [ _sales_order_type(), _purchase_order_type(), _sales_quotation_type(), _request_quotation_type() ];
 }
 
 sub init_type {
@@ -872,8 +900,8 @@ sub init_type {
 sub init_cv {
   my ($self) = @_;
 
-  my $cv = $self->type eq _sales_order_type()    ? 'customer'
-         : $self->type eq _purchase_order_type() ? 'vendor'
+  my $cv = (any { $self->type eq $_ } (_sales_order_type(),    _sales_quotation_type()))   ? 'customer'
+         : (any { $self->type eq $_ } (_purchase_order_type(), _request_quotation_type())) ? 'vendor'
          : die "Not a valid type for order";
 
   return $cv;
@@ -1007,7 +1035,8 @@ sub _make_order {
   # order here solves this problem.
   my $order;
   $order   = SL::DB::Manager::Order->find_by(id => $::form->{id}) if $::form->{id};
-  $order ||= SL::DB::Order->new(orderitems => []);
+  $order ||= SL::DB::Order->new(orderitems => [],
+                                quotation  => (any { $self->type eq $_ } (_sales_quotation_type(), _request_quotation_type())));
 
   my $form_orderitems               = delete $::form->{order}->{orderitems};
   my $form_periodic_invoices_config = delete $::form->{order}->{periodic_invoices_config};
@@ -1226,6 +1255,7 @@ sub _pre_render {
   $self->{all_delivery_terms}       = SL::DB::Manager::DeliveryTerm->get_all_sorted();
   $self->{current_employee_id}      = SL::DB::Manager::Employee->current->id;
   $self->{periodic_invoices_status} = $self->_get_periodic_invoices_status($self->order->periodic_invoices_config);
+  $self->{order_probabilities}      = [ map { { title => ($_ * 10) . '%', id => $_ * 10 } } (0..10) ];
 
   my $print_form = Form->new('');
   $print_form->{type}      = $self->type;
@@ -1266,8 +1296,9 @@ sub _pre_render {
 sub _setup_edit_action_bar {
   my ($self, %params) = @_;
 
-  my $deletion_allowed = (($self->cv eq 'customer') && $::instance_conf->get_sales_order_show_delete)
-                      || (($self->cv eq 'vendor')   && $::instance_conf->get_purchase_order_show_delete);
+  my $deletion_allowed = (any { $self->type eq $_ } (_sales_quotation_type(), _request_quotation_type()))
+                      || (($self->type eq _sales_order_type())    && $::instance_conf->get_sales_order_show_delete)
+                      || (($self->type eq _purchase_order_type()) && $::instance_conf->get_purchase_order_show_delete);
 
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
@@ -1282,6 +1313,7 @@ sub _setup_edit_action_bar {
           t8('Save and Delivery Order'),
           call      => [ 'kivi.Order.save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts ],
           checks    => [ 'kivi.Order.check_save_active_periodic_invoices' ],
+          only_if   => (any { $self->type eq $_ } (_sales_order_type(), _purchase_order_type()))
         ],
         action => [
           t8('Save and Invoice'),
@@ -1435,6 +1467,14 @@ sub _purchase_order_type {
   'purchase_order';
 }
 
+sub _sales_quotation_type {
+  'sales_quotation';
+}
+
+sub _request_quotation_type {
+  'request_quotation';
+}
+
 1;
 
 __END__
index 2a57dca..7832b2e 100644 (file)
@@ -1035,7 +1035,7 @@ sub orders {
   $form->{l_open}              = $form->{l_closed} = "Y" if ($form->{open}      && $form->{closed});
   $form->{l_delivered}         = "Y"                     if ($form->{delivered} && $form->{notdelivered});
   $form->{l_periodic_invoices} = "Y"                     if ($form->{periodic_invoices_active} && $form->{periodic_invoices_inactive});
-  $form->{l_edit_exp}          = "Y"                     if $::instance_conf->get_feature_experimental && (any { $form->{type} eq $_ } qw(sales_order purchase_order));
+  $form->{l_edit_exp}          = "Y"                     if $::instance_conf->get_feature_experimental && (any { $form->{type} eq $_ } qw(sales_order purchase_order sales_quotation request_quotation));
   map { $form->{"l_${_}"} = 'Y' } qw(order_probability expected_billing_date expected_netamount) if $form->{l_order_probability_expected_billing_date};
 
   my $attachment_basename;
@@ -1265,7 +1265,7 @@ sub orders {
 
     $row->{$ordnumber}->{link} = $edit_url . "&id=" . E($oe->{id}) . "&callback=${callback}";
 
-    $row->{edit_exp}->{data}   = $oe->{ordnumber};
+    $row->{edit_exp}->{data}   = $oe->{$ordnumber};
     $row->{edit_exp}->{link}   = build_std_url('script=controller.pl', 'action=Order/edit', "type=$form->{type}", 'id=' . E($oe->{id}));
 
     my $row_set = [ $row ];
index 39e0191..18756f2 100644 (file)
@@ -1,6 +1,6 @@
 namespace('kivi.Order', function(ns) {
   ns.check_cv = function() {
-    if ($('#type').val() == 'sales_order') {
+    if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
       if ($('#order_customer_id').val() === '') {
         alert(kivi.t8('Please select a customer.'));
         return false;
@@ -610,13 +610,13 @@ namespace('kivi.Order', function(ns) {
 });
 
 $(function(){
-  if ($('#type').val() == 'sales_order') {
+  if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
     $('#order_customer_id').change(kivi.Order.reload_cv_dependant_selections);
   } else {
     $('#order_vendor_id').change(kivi.Order.reload_cv_dependant_selections);
   }
 
-  if ($('#type').val() == 'sales_order') {
+  if ($('#type').val() == 'sales_order' || $('#type').val() == 'sales_quotation' ) {
     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) });
   } else {
     $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) });
index b26b75b..e36c7c9 100644 (file)
@@ -1,3 +1,12 @@
+- parent: ar
+  id: ar_add_quotation_experimental
+  name: Add Quotation (experimental)
+  icon: quotation_add
+  order: 250
+  access: sales_quotation_edit & client/feature_experimental
+  params:
+    action: Order/add
+    type: sales_quotation
 - parent: ar
   id: ar_add_sales_order_experimental
   name: Add Sales Order (experimental)
@@ -8,6 +17,15 @@
     action: Order/add
     type: sales_order
 
+- parent: ap
+  id: ap_add_rfq_experimental
+  name: Add RFQ (experimental)
+  icon: rfq_add
+  order: 150
+  access: request_quotation_edit & client/feature_experimental
+  params:
+    action: Order/add
+    type: request_quotation
 - parent: ap
   id: ap_add_purchase_order_experimental
   name: Add Purchase Order (experimental)
index d8d8a86..18226ab 100644 (file)
@@ -6,15 +6,19 @@
 
 <table>
   <tr><td colspan="100%">
-    <b>[%- 'Serial No.' | $T8 %]</b>&nbsp;
-    [%- L.input_tag("order.orderitems[].serialnumber", ITEM.serialnumber, size = 15) %]&nbsp;
+    [%- IF (TYPE == "sales_order" || TYPE == "purchase_order") %]
+      <b>[%- 'Serial No.' | $T8 %]</b>&nbsp;
+      [%- L.input_tag("order.orderitems[].serialnumber", ITEM.serialnumber, size = 15) %]&nbsp;
+    [%- END %]
     <b>[%- 'Project' | $T8 %]</b>&nbsp;
     [% P.project.picker("order.orderitems[].project_id", ITEM.project_id, size = 15) %]&nbsp;
-    <b>[%- 'Reqdate' | $T8 %]</b>&nbsp;
-    [% L.date_tag("order.orderitems[].reqdate", ITEM.reqdate) %]&nbsp;
+    [%- IF (TYPE == "sales_order" || TYPE == "purchase_order") %]
+      <b>[%- 'Reqdate' | $T8 %]</b>&nbsp;
+      [% L.date_tag("order.orderitems[].reqdate", ITEM.reqdate) %]&nbsp;
+    [%- END %]
     <b>[%- 'Subtotal' | $T8 %]</b>&nbsp;
     [% L.yes_no_tag("order.orderitems[].subtotal", ITEM.subtotal) %]&nbsp;
-    [%- IF TYPE == "sales_order" %]
+    [%- IF (TYPE == "sales_order" || TYPE == "sales_quotation") %]
       <b>[%- 'Ertrag' | $T8 %]</b>&nbsp;
         <span name="linemargin">
           <span[%- IF ITEM.marge_total < 0 -%] class="plus0"[%- END -%]>
index d41e57b..877e5fd 100644 (file)
           </tr>
           [% END %]
 
+          [%- IF (SELF.type == "sales_order" || SELF.type == "purchase_order") -%]
           <tr>
             <th width="70%" align="right" nowrap>[% 'Order Number' | $T8 %]</th>
             <td>[% L.input_tag('order.ordnumber', SELF.order.ordnumber, size = 11) %]</td>
           </tr>
+          [%- END -%]
 
+          [%- IF (SELF.type == "sales_order" || SELF.type == "sales_quotation") -%]
+            [%- SET quo_nr_txt = 'Quotation Number' -%]
+          [%- ELSE -%]
+            [%- SET quo_nr_txt = 'RFQ Number' -%]
+          [%- END -%]
           <tr>
-            <th width="70%" align="right" nowrap>[% 'Quotation Number' | $T8 %]</th>
+            <th width="70%" align="right" nowrap>[% quo_nr_txt | $T8 %]</th>
             <td>[% L.input_tag('order.quonumber', SELF.order.quonumber, size = 11) %]</td>
           </tr>
 
+          [%- IF (SELF.type == "sales_order" || SELF.type == "purchase_order") -%]
           <tr>
             <th width="70%" align="right" nowrap>[% 'Customer Order Number' | $T8 %]</th>
             <td>[% L.input_tag('order.cusordnumber', SELF.order.cusordnumber, size = 11) %]</td>
           </tr>
-
+          [%- END -%]
+
+          [%- IF (SELF.type == "sales_order" || SELF.type == "purchase_order") -%]
+            [%- SET transdate_txt = 'Order Date' -%]
+          [%- ELSIF SELF.type == "sales_quotation" -%]
+            [%- SET transdate_txt = 'Quotation Date' -%]
+          [%- ELSE -%]
+            [%- SET transdate_txt = 'RFQ Date' -%]
+          [%- END -%]
           <tr>
-            <th width="70%" align="right" nowrap>[% 'Order Date' | $T8 %]</th>
+            <th width="70%" align="right" nowrap>[% transdate_txt | $T8 %]</th>
             <td>[% L.date_tag('order.transdate', SELF.order.transdate) %]</td>
           </tr>
 
+          [%- IF (SELF.type == "sales_order" || SELF.type == "purchase_order") -%]
+            [%- SET reqdate_txt = 'Reqdate' -%]
+          [%- ELSIF SELF.type == "sales_quotation" -%]
+            [%- SET reqdate_txt = 'Valid until' -%]
+          [%- ELSE -%]
+            [%- SET reqdate_txt = 'Required by' -%]
+          [%- END -%]
           <tr>
-            <th width="70%" align="right" nowrap>[% 'Reqdate' | $T8 %]</th>
+            <th width="70%" align="right" nowrap>[% reqdate_txt | $T8 %]</th>
             <td>[% L.date_tag('order.reqdate', SELF.order.reqdate) %]</td>
           </tr>
 
+          [%- IF SELF.type == "sales_quotation" -%]
+          <tr>
+            <th width="70%" align="right" nowrap>[% 'Order probability' | $T8 %]</th>
+            <td>[%- L.select_tag('order.order_probability', SELF.order_probabilities, title='title', default=SELF.order.order_probability) %]%</td>
+          </tr>
+          <tr>
+            <th width="70%" align="right" nowrap>[% 'Expected billing date' | $T8 %]</th>
+            <td>[%- L.date_tag('order.expected_billing_date', SELF.order.expected_billing_date) %]</td>
+          </tr>
+          [%- END %]
+
           <tr>
             <th width="70%" align="right" nowrap>[% 'Insert Date' | $T8 %]</th>
             <td>[% SELF.order.itime_as_date %]</td>