Verknüpfte Belege: Unterstützung für Pflichtenhefte
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 9 Jan 2014 11:25:32 +0000 (12:25 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Tue, 1 Apr 2014 11:12:24 +0000 (13:12 +0200)
SL/Controller/RecordLinks.pm
SL/DB/Helper/LinkedRecords.pm
SL/DB/RequirementSpec.pm
SL/Presenter.pm
SL/Presenter/Record.pm
SL/Presenter/RequirementSpec.pm [new file with mode: 0644]
js/locale/de.js
locale/de/all
templates/webpages/record_links/add_filter.html
templates/webpages/record_links/add_list.html

index 8d6adc7..cffbd94 100644 (file)
@@ -12,6 +12,7 @@ use SL::DB::DeliveryOrder;
 use SL::DB::Invoice;
 use SL::DB::PurchaseInvoice;
 use SL::DB::RecordLink;
+use SL::DB::RequirementSpec;
 use SL::JSON;
 use SL::Locale::String;
 
@@ -23,7 +24,15 @@ use Rose::Object::MakeMethods::Generic
 __PACKAGE__->run_before('check_object_params', only => [ qw(ajax_list ajax_delete ajax_add_select_type ajax_add_filter ajax_add_list ajax_add_do) ]);
 __PACKAGE__->run_before('check_link_params',   only => [ qw(                                                           ajax_add_list ajax_add_do) ]);
 
-my @link_types = (
+my %link_type_defaults = (
+  filter      => 'type_filter',
+  project     => 'globalproject',
+  description => 'transaction_description',
+  date        => 'transdate',
+);
+
+my @link_type_specifics = (
+  { title => t8('Requirement spec'),        type => 'requirement_spec',        model => 'RequirementSpec', number => 'id', project => 'project', description => 'title', date => undef, filter => undef, },
   { title => t8('Sales quotation'),         type => 'sales_quotation',         model => 'Order',           number => 'quonumber', },
   { title => t8('Sales Order'),             type => 'sales_order',             model => 'Order',           number => 'ordnumber', },
   { title => t8('Sales delivery order'),    type => 'sales_delivery_order',    model => 'DeliveryOrder',   number => 'donumber',  },
@@ -34,6 +43,7 @@ my @link_types = (
   { title => t8('Purchase Invoice'),        type => 'purchase_invoice',        model => 'PurchaseInvoice', number => 'invnumber', },
 );
 
+my @link_types = map { +{ %link_type_defaults, %{ $_ } } } @link_type_specifics;
 
 #
 # actions
@@ -103,22 +113,28 @@ sub action_ajax_add_filter {
 sub action_ajax_add_list {
   my ($self) = @_;
 
-  my $manager = 'SL::DB::Manager::' . $self->link_type_desc->{model};
-  my $vc      = $self->link_type =~ m/sales_|^invoice$/ ? 'customer' : 'vendor';
+  my $manager     = 'SL::DB::Manager::' . $self->link_type_desc->{model};
+  my $vc          = $self->link_type =~ m/sales_|^invoice|requirement_spec$/ ? 'customer' : 'vendor';
+  my $project     = $self->link_type_desc->{project};
+  my $description = $self->link_type_desc->{description};
+  my $filter      = $self->link_type_desc->{filter};
 
-  my @where = $manager->type_filter($self->link_type);
+  my @where = $filter ? $manager->$filter($self->link_type) : ();
   push @where, ("${vc}.${vc}number"     => { ilike => '%' . $::form->{vc_number} . '%' })               if $::form->{vc_number};
   push @where, ("${vc}.name"            => { ilike => '%' . $::form->{vc_name}   . '%' })               if $::form->{vc_name};
-  push @where, (transaction_description => { ilike => '%' . $::form->{transaction_description} . '%' }) if $::form->{transaction_description};
-  push @where, (globalproject_id        => $::form->{globalproject_id})                                 if $::form->{globalproject_id};
+  push @where, ($description            => { ilike => '%' . $::form->{transaction_description} . '%' }) if $::form->{transaction_description};
+  push @where, ("${project}_id"         => $::form->{globalproject_id})                                 if $::form->{globalproject_id};
 
-  my $objects = $manager->get_all_sorted(where => \@where, with_objects => [ $vc, 'globalproject' ]);
+  my $objects = $manager->get_all_sorted(where => \@where, with_objects => [ $vc, $project ]);
   my $output  = $self->render(
     'record_links/add_list',
-    { output      => 0 },
-    OBJECTS       => $objects,
-    vc            => $vc,
-    number_column => $self->link_type_desc->{number},
+    { output => 0 },
+    OBJECTS            => $objects,
+    vc                 => $vc,
+    number_column      => $self->link_type_desc->{number},
+    description_column => $description,
+    project_column     => $project,
+    date_column        => $self->link_type_desc->{date},
   );
 
   my %result = ( count => scalar(@{ $objects }), html => $output );
index dd22863..3c26b01 100644 (file)
@@ -149,6 +149,7 @@ sub sort_linked_records {
                   'SL::DB::DeliveryOrder'   => sub { $_[0]->donumber },
                   'SL::DB::Invoice'         => sub { $_[0]->invnumber },
                   'SL::DB::PurchaseInvoice' => sub { $_[0]->invnumber },
+                  'SL::DB::RequirementSpec' => sub { $_[0]->id },
                   UNKNOWN                   => '9999999999999999',
                 );
   my $number_xtor = sub {
@@ -165,6 +166,7 @@ sub sort_linked_records {
 
   my %scores;
   %scores = ( 'SL::DB::SalesProcess'    =>  10,
+              'SL::DB::RequirementSpec' =>  15,
               'SL::DB::Order'           =>  sub { $scores{ $_[0]->type } },
               sales_quotation           =>  20,
               sales_order               =>  30,
index e1298ec..e5dae7e 100644 (file)
@@ -302,6 +302,12 @@ sub invalidate_version {
   );
 }
 
+sub compare_to {
+  my ($self, $other) = @_;
+
+  return $self->id <=> $other->id;
+}
+
 1;
 __END__
 
index ba24b82..ee0e495 100644 (file)
@@ -15,6 +15,7 @@ use SL::Presenter::Order;
 use SL::Presenter::Part;
 use SL::Presenter::Project;
 use SL::Presenter::Record;
+use SL::Presenter::RequirementSpec;
 use SL::Presenter::RequirementSpecItem;
 use SL::Presenter::RequirementSpecTextBlock;
 use SL::Presenter::SepaExport;
index 4f9a518..2bbaaf6 100644 (file)
@@ -27,6 +27,7 @@ sub grouped_record_list {
   my %groups = _sort_grouped_lists(_group_records($list));
   my $output = '';
 
+  $output .= _requirement_spec_list(       $self, $groups{requirement_specs},        %params) if $groups{requirement_specs};
   $output .= _sales_quotation_list(        $self, $groups{sales_quotations},         %params) if $groups{sales_quotations};
   $output .= _sales_order_list(            $self, $groups{sales_orders},             %params) if $groups{sales_orders};
   $output .= _sales_delivery_order_list(   $self, $groups{sales_delivery_orders},    %params) if $groups{sales_delivery_orders};
@@ -142,6 +143,7 @@ sub _group_records {
   my ($list) = @_;
 
   my %matchers = (
+    requirement_specs        => sub { (ref($_[0]) eq 'SL::DB::RequirementSpec')                                         },
     sales_quotations         => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('sales_quotation')   },
     sales_orders             => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('sales_order')       },
     sales_delivery_orders    => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder')   &&  $_[0]->is_sales                     },
@@ -182,6 +184,24 @@ sub _sort_grouped_lists {
   return %groups;
 }
 
+sub _requirement_spec_list {
+  my ($self, $list, %params) = @_;
+
+  return $self->record_list(
+    $list,
+    title   => $::locale->text('Requirement specs'),
+    type    => 'requirement_spec',
+    columns => [
+      [ $::locale->text('Requirement spec number'), sub { $self->requirement_spec($_[0], display => 'table-cell') } ],
+      [ $::locale->text('Customer'),                'customer'                                                      ],
+      [ $::locale->text('Title'),                   'title'                                                         ],
+      [ $::locale->text('Project'),                 'project',                                                      ],
+      [ $::locale->text('Status'),                  sub { $_[0]->status->description }                              ],
+    ],
+    %params,
+  );
+}
+
 sub _sales_quotation_list {
   my ($self, $list, %params) = @_;
 
diff --git a/SL/Presenter/RequirementSpec.pm b/SL/Presenter/RequirementSpec.pm
new file mode 100644 (file)
index 0000000..5cca5a8
--- /dev/null
@@ -0,0 +1,27 @@
+package SL::Presenter::RequirementSpec;
+
+use strict;
+
+use parent qw(Exporter);
+
+use Exporter qw(import);
+our @EXPORT = qw(requirement_spec);
+
+use Carp;
+
+sub requirement_spec {
+  my ($self, $requirement_spec, %params) = @_;
+
+  $params{display} ||= 'inline';
+
+  croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
+
+  my $text = join '', (
+    $params{no_link} ? '' : '<a href="controller.pl?action=RequirementSpec/show&amp;id=' . $self->escape($requirement_spec->id) . '">',
+    $self->escape($requirement_spec->id),
+    $params{no_link} ? '' : '</a>',
+  );
+  return $self->escaped_text($text);
+}
+
+1;
index 9c54d61..2b80e96 100644 (file)
@@ -57,7 +57,9 @@ namespace("kivi").setupLocale({
 "The selected database is still configured for client \"#1\". If you delete the database that client will stop working until you re-configure it. Do you still want to delete the database?":"Die auswählte Datenbank ist noch für Mandant \"#1\" konfiguriert. Wenn Sie die Datenbank löschen, wird der Mandanten nicht mehr funktionieren, bis er anders konfiguriert wurde. Wollen Sie die Datenbank trotzdem löschen?",
 "There is one or more sections for which no part has been assigned yet; therefore creating the new record is not possible yet.":"Es gibt einen oder mehrere Abschnitte ohne Artikelzuweisung; daher kann der neue Beleg noch nicht erstellt werden.",
 "Time/cost estimate actions":"Aktionen für Kosten-/Zeitabschätzung",
+"Title":"Titel",
 "Toggle marker":"Markierung umschalten",
+"Transaction description":"Vorgangsbezeichnung",
 "Update":"Erneuern",
 "Update quotation/order":"Auftrag/Angebot aktualisieren",
 "Version actions":"Aktionen für Versionen"
index 1c56c59..0990cba 100755 (executable)
@@ -1068,10 +1068,7 @@ $self->{texts} = {
   'Filter for customer variables' => 'Filter für benutzerdefinierte Kundenvariablen',
   'Filter for item variables'   => 'Filter für benutzerdefinierte Artikelvariablen',
   'Filter parts'                => 'Artikel filtern',
-  'Financial Controlling'       => 'Finanzcontrolling',
-  'Financial Controlling Report' => 'Finanzcontrollingbericht',
   'Financial Overview'          => 'Finanzübersicht',
-  'Financial controlling report for open sales orders' => 'Finanzcontrollingbericht für offene Aufträge',
   'Financial overview for #1'   => 'Finanzübersicht für #1',
   'Finish'                      => 'Abschlie&szlig;en',
   'First 20 Lines'              => 'Nur erste 20 Datensätze',
@@ -1920,8 +1917,10 @@ $self->{texts} = {
   'Requirement Spec Types'      => 'Pflichtenhefttypen',
   'Requirement Spec Version'    => 'Pflichtenheftversion',
   'Requirement Specs'           => 'Pflichtenhefte',
+  'Requirement spec'            => 'Pflichtenheft',
   'Requirement spec actions'    => 'Pflichtenheftaktionen',
   'Requirement spec function block #1 with #2 sub function blocks; description: "#3"' => 'Pflichtenheft-Funktionsblock #1 mit #2 Unterfunktionsblöcken; Beschreibung: "#3"',
+  'Requirement spec number'     => 'Pflichtenheftnummer',
   'Requirement spec picture "#1"' => 'Pflichtenheftbild "#1"',
   'Requirement spec section #1 "#2" with #3 function blocks and a total of #4 sub function blocks; preamble: "#5"' => 'Pflichtenheftabschnitt #1 "#2" mit #3 Funktionsblöcken und insgesamt #4 Unterfunktionsblöcken; Einleitung: "#5"',
   'Requirement spec sub function block #1; description: "#2"' => 'Pflichtenheft-Unterfunktionsblock #1; Beschreibung: "#2"',
index be286e3..39469f5 100644 (file)
@@ -10,7 +10,7 @@
  <table>
   <tr>
    <td>[%- LxERP.t8("Link to") %]:</td>
-   <td>[% L.select_tag('link_type', LINK_TYPES, default=DEFAULT_LINK_TYPE, style=style) %]</td>
+   <td>[% L.select_tag('link_type', LINK_TYPES, default=DEFAULT_LINK_TYPE, style=style, id='record_links_add_filter_link_type') %]</td>
   </tr>
 
   <tr>
@@ -37,7 +37,7 @@
   </tr>
 
   <tr>
-   <td>[%- LxERP.t8("Transaction description") %]:</td>
+   <td><span id="record_links_add_filter_title">[%- LxERP.t8("Transaction description") %]</span>:</td>
    <td>[% L.input_tag('transaction_description', '', style=style) %]</td>
   </tr>
  </table>
 <!--
 $(function() {
   $('#record_links_add input[name=vc_name]').focus();
+  $('#record_links_add_filter_link_type').change(function() {
+    var title = $('#record_links_add_filter_link_type').val() == 'requirement_spec' ? kivi.t8('Title') : kivi.t8('Transaction description');
+    $('#record_links_add_filter_title').html(title);
+  });
 });
 
 function record_links_reset_form() {
index 9ca7b45..edbadb2 100644 (file)
@@ -7,8 +7,10 @@
   <th>[% L.checkbox_tag('record_links_check_all') %]</th>
   <th>[% IF vc == 'customer' %][%- LxERP.t8("Customer") %][%- ELSE %][%- LxERP.t8("Vendor") %][%- END %]</th>
   <th>[%- LxERP.t8("Number") %]</th>
-  <th>[%- LxERP.t8("Date") %]</th>
-  <th>[%- LxERP.t8("Transaction description") %]</th>
+  [% IF date_column %]
+   <th>[%- LxERP.t8("Date") %]</th>
+  [% END %]
+  <th>[% IF SELF.link_type == 'requirement_spec' %][%- LxERP.t8("Title") %][% ELSE %][%- LxERP.t8("Transaction description") %][% END %]</th>
   <th>[%- LxERP.t8("Project") %]</th>
  </tr>
 
   <td>[% L.checkbox_tag('link_id[]', value=object.id) %]</td>
   <td>[%- HTML.escape(object.$vc.name) %]</td>
   <td>[%- HTML.escape(object.$number_column) %]</td>
-  <td>[%- HTML.escape(object.transdate.to_kivitendo) %]</td>
-  <td>[%- HTML.escape(object.transaction_description) %]</td>
-  <td>[%- P.project(object.globalproject, no_link=1) %]</td>
+  [% IF date_column %]
+   <td>[%- HTML.escape(object.$date_column.to_kivitendo) %]</td>
+  [% END %]
+  <td>[%- HTML.escape(object.$description_column) %]</td>
+  <td>[%- P.project(object.$project_column, no_link=1) %]</td>
  </tr>
  [%- END %]
 </table>