FiBu Schellsuche in Headerzeile
authorG. Richardson <information@kivitendo-premium.de>
Fri, 4 Apr 2014 11:09:26 +0000 (13:09 +0200)
committerG. Richardson <information@kivitendo-premium.de>
Thu, 4 Dec 2014 12:29:31 +0000 (13:29 +0100)
neues Ajax Autocompletefeld im Header für Benutzer mit FiBu-Rechten,
welches Rechnungsnummern und Kunden-/Lieferantennamen durchsucht. Durch
die Auswahl im Dropdown gelangt man direkt zu dem Beleg.

SL/Controller/GL.pm [new file with mode: 0644]
SL/DB/GLTransaction.pm
SL/DB/Invoice.pm
SL/DB/PurchaseInvoice.pm
doc/changelog
js/glquicksearch.js [new file with mode: 0644]
locale/de/all
templates/webpages/menu/header.html
templates/webpages/menu/menunew.html
templates/webpages/menu/menuv3.html

diff --git a/SL/Controller/GL.pm b/SL/Controller/GL.pm
new file mode 100644 (file)
index 0000000..ce3799d
--- /dev/null
@@ -0,0 +1,107 @@
+package SL::Controller::GL;
+
+use strict;
+use parent qw(SL::Controller::Base);
+
+use SL::DB::GLTransaction;
+use SL::DB::Invoice;
+use SL::DB::PurchaseInvoice;
+use SL::DB::AccTransaction;
+use SL::Locale::String qw(t8);
+
+__PACKAGE__->run_before('check_auth');
+
+sub action_quicksearch {
+
+  my ($self, %params) = @_;
+  
+  my $limit = $::form->{limit} || 40; # max number of results per type (AR/AP/GL)
+  my $term  = $::form->{term}  || '';
+  
+  my $descriptionquery = { ilike => '%' . $term . '%' };
+  my $referencequery   = { ilike => '%' . $term . '%' };
+  my $apinvnumberquery = { ilike => '%' . $term . '%' };
+  my $namequery        = { ilike => '%' . $term . '%' };
+  my $arinvnumberquery = { ilike => '%' . $term       };
+  # ar match is more restrictive. Left fuzzy beginning so it also matches "Storno zu $INVNUMBER"
+  # and numbers like 000123 if you only enter 123.
+  # When used in quicksearch short numbers like 1 or 11 won't match because of the
+  # ajax autocomplete minlimit of 3 characters
+
+  my (@glfilter, @arfilter, @apfilter);
+
+  push( @glfilter, (or => [ description => $descriptionquery, reference => $referencequery ] ) );
+  push( @arfilter, (or => [ invnumber   => $arinvnumberquery, name      => $namequery ] ) );
+  push( @apfilter, (or => [ invnumber   => $apinvnumberquery, name      => $namequery ] ) );
+
+  my $gls = SL::DB::Manager::GLTransaction->get_all(  query => [ @glfilter ], limit => $limit, sort_by => 'transdate DESC');
+  my $ars = SL::DB::Manager::Invoice->get_all(        query => [ @arfilter ], limit => $limit, sort_by => 'transdate DESC', with_objects => [ 'customer' ]);
+  my $aps = SL::DB::Manager::PurchaseInvoice->get_all(query => [ @apfilter ], limit => $limit, sort_by => 'transdate DESC', with_objects => [ 'vendor' ]);
+
+  # calculate an amount to be displayed for gl transaction
+  foreach my $gl ( @$gls ) {
+    my $amount = 0;
+    my $acc_trans_lines = SL::DB::Manager::AccTransaction->get_all(query => [ trans_id => $gl->id ]);
+    foreach my $acc_trans_line ( @$acc_trans_lines ) {
+      $amount += $acc_trans_line->amount if $acc_trans_line->amount > 0 ;
+    };
+    $gl->{'amount'} = $amount;
+  };
+
+  my $gldata = [
+    map(
+      {
+        {
+           transdate => DateTime->from_object(object => $_->transdate)->ymd(),
+           label     => $_->abbreviation. ": " . $_->description . " " . $_->reference . " " . $::form->format_amount(\%::myconfig, $_->{'amount'},2). " (" . $_->transdate->to_lxoffice . ")" ,
+           value     => '',
+           url       => 'gl.pl?action=edit&id=' . $_->id,
+        }
+      }
+      @{$gls}
+    ),
+  ];
+
+  my $ardata = [
+    map(
+      {
+        {
+           transdate => DateTime->from_object(object => $_->transdate)->ymd(),
+           label     => $_->abbreviation . ": " . $_->invnumber . "   " . $_->customer->name . " " . $::form->format_amount(\%::myconfig, $_->amount,2)  . " (" . $_->transdate->to_lxoffice . ")" ,
+           value     => "",
+           url       => ($_->invoice ? "is" : "ar" ) . '.pl?action=edit&id=' . $_->id,
+        }
+      }
+      @{$ars}
+    ),
+  ];
+
+  my $apdata = [
+    map(
+      {
+        {
+           transdate => DateTime->from_object(object => $_->transdate)->ymd(),
+           label     => $_->abbreviation . ": " . $_->invnumber . " " . $_->vendor->name . " " . $::form->format_amount(\%::myconfig, $_->amount,2)  . " (" . $_->transdate->to_lxoffice . ")" ,
+           value     => "",
+           url       => ($_->invoice ? "ir" : "ap" ) . '.pl?action=edit&id=' . $_->id,
+        }
+      }
+      @{$aps}
+    ),
+  ];
+
+  my $data;
+  push(@{$data},@{$gldata});
+  push(@{$data},@{$ardata});
+  push(@{$data},@{$apdata});
+
+  @$data = reverse sort { $a->{'transdate_sort'} cmp $b->{'transdate_sort'} } @$data;
+
+  $self->render(\SL::JSON::to_json($data), { layout => 0, type => 'json' });
+}
+
+sub check_auth {
+  $::auth->assert('general_ledger');
+}
+
+1;
index 352de03..078e2b9 100644 (file)
@@ -9,4 +9,13 @@ __PACKAGE__->meta->initialize;
 # Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
 __PACKAGE__->meta->make_manager_class;
 
+sub abbreviation {
+  my $self = shift;
+
+  my $abbreviation = $::locale->text('GL Transaction (abbreviation)');
+  $abbreviation   .= "(" . $::locale->text('Storno (one letter abbreviation)') . ")" if $self->storno;
+  return $abbreviation;
+
+}
+
 1;
index f0f3d0a..d734003 100644 (file)
@@ -17,6 +17,7 @@ use SL::DB::Helper::LinkedRecords;
 use SL::DB::Helper::PriceTaxCalculator;
 use SL::DB::Helper::PriceUpdater;
 use SL::DB::Helper::TransNumberGenerator;
+use SL::Locale::String qw(t8);
 
 __PACKAGE__->meta->add_relationship(
   invoiceitems => {
@@ -317,6 +318,17 @@ sub displayable_state {
   return $self->closed ? $::locale->text('closed') : $::locale->text('open');
 }
 
+sub abbreviation {
+  my $self = shift;
+
+  return t8('AR Transaction (abbreviation)') if !$self->invoice;
+  return t8('Credit note (one letter abbreviation)') if $self->type eq 'credit_note' && $self->amount < 0 && !$self->storno;
+  return t8('Invoice (one letter abbreviation)') . "(" . t8('Storno (one letter abbreviation)') . ")" if $self->type ne 'credit_note' && $self->amount < 0 &&  $self->storno;
+  return t8('Credit note (one letter abbreviation)') . "(" . t8('Storno (one letter abbreviation)') . ")" if $self->type eq 'credit_note' && $self->amount > 0 &&  $self->storno;
+  return t8('Invoice (one letter abbreviation)');
+
+}
+
 sub date {
   goto &transdate;
 }
index 3245e4b..b3d3500 100644 (file)
@@ -7,6 +7,8 @@ use Carp;
 use SL::DB::MetaSetup::PurchaseInvoice;
 use SL::DB::Manager::PurchaseInvoice;
 use SL::DB::Helper::LinkedRecords;
+use SL::Locale::String qw(t8);
+
 # The calculator hasn't been adjusted for purchase invoices yet.
 # use SL::DB::Helper::PriceTaxCalculator;
 
@@ -52,4 +54,13 @@ sub date {
   goto &transdate;
 }
 
+sub abbreviation {
+  my $self = shift;
+
+  return t8('AP Transaction (abbreviation)') if !$self->invoice && !$self->storno;
+  return t8('AP Transaction (abbreviation)') . '(' . t8('Storno (one letter abbreviation)') . ')' if !$self->invoice && $self->storno;
+  return t8('Invoice (one letter abbreviation)'). '(' . t8('Storno (one letter abbreviation)') . ')' if $self->storno;
+  return t8('Invoice (one letter abbreviation)');
+
+}
 1;
index a4377a5..e5809f5 100644 (file)
@@ -77,6 +77,9 @@ Kleinere neue Features und Detailverbesserungen:
 - Verkaufsangebotsgültigkeit konfigurierbar per Intervall (nächster Werktag + x Tage)
 
 - Schnelllöschen von einzelnen Positionen (Ein X vor jeder Zeile)
+
+- FiBu Schnellsuche in Headerzeile, um nach Belegen zu suchen
+
 2014-02-28 - Release 3.1.0
 
 Größere neue Features:
diff --git a/js/glquicksearch.js b/js/glquicksearch.js
new file mode 100644 (file)
index 0000000..2b8b3df
--- /dev/null
@@ -0,0 +1,14 @@
+$(function() {
+  $( "#glquicksearch" ).autocomplete({
+    source: "controller.pl?action=GL/quicksearch",
+    minLength: 3,
+    select: function(event, ui) {
+           var url = ui.item.url;
+           if(url != '#') {
+               location.href = url;
+           }
+       },
+    html: false,
+    autoFocus: true
+  });
+});
index edad436..295ee31 100755 (executable)
@@ -1158,6 +1158,8 @@ $self->{texts} = {
   'Function/position'           => 'Funktion/Position',
   'Fwd'                         => 'Vorw&auml;rts',
   'GL Transaction'              => 'Dialogbuchung',
+  'GL Transaction (abbreviation)' => 'DB',
+  'GL search'                   => 'FiBu Suche',
   'GL transactions changeable'  => 'Änderbarkeit von Dialogbuchungen',
   'Gegenkonto'                  => 'Gegenkonto',
   'Gender'                      => 'Geschlecht',
index b798c11..9500438 100644 (file)
@@ -7,6 +7,9 @@
     [<a href="JavaScript:top.print();" title="[% 'Hardcopy' | $T8 %]">[% 'Print' | $T8 %]</a>]
     [<a href="Javascript:top.history.back();" title="[% 'Go one step back' | $T8 %]">[% 'Back' | $T8 %]</a>]
     [<a href="Javascript:top.history.forward();" title="[% 'Go one step forward' | $T8 %]">[% 'Fwd' | $T8 %]</a>]
+[%- IF AUTH.assert('general_ledger', 1) %]
+    [[% 'GL search' | $T8 %]: <input id="glquicksearch" name="glquicksearch" type="text" class="ui-widget" size="20" maxlength="20">]
+[%- END %]
  </span>
 [%- END %]
  <span class="frame-header-element frame-header-right">
@@ -20,3 +23,6 @@
   <img src="image/[% IF MYCONFIG.stylesheet == 'lx-office-erp.css' %]spinner-blue.gif[% ELSE %]spinner-white.gif[% END %]" alt="[% LxERP.t8('Loading...') %]">
  </span>
 </div>
+[% IF AUTH.assert('general_ledger', 1) %]
+ <script type="text/javascript" src="js/glquicksearch.js"></script>
+[% END %]
index 55fcab8..fc0e326 100644 (file)
@@ -19,7 +19,9 @@ $(clockon);
   <span class="frame-header-element frame-header-left">
    [<a href="login.pl?action=company_logo" target="_blank">[% 'new Window' | $T8 %]</a>]
    [<a href="JavaScript:top.print()">[% 'print' | $T8 %]</a>]
-   [[% 'Search contacts' | $T8 %] <input size="15" name="search_term" id="search_term" onkeydown="return on_keydown_quicksearch($('#search_term'), event)">]
+[%- IF AUTH.assert('general_ledger', 1) %]
+    [[% 'GL search' | $T8 %]: <input id="glquicksearch" name="glquicksearch" type="text" class="ui-widget" size="20" maxlength="20">]
+[%- END %]
   </span>
   <span class="frame-header-element frame-header-right">
    [[% 'User' | $T8 %]: [% MYCONFIG.login | html %] -
@@ -98,3 +100,6 @@ function open_url(url, target) {
 
     -->
  </script>
+[% IF AUTH.assert('general_ledger', 1) %]
+ <script type="text/javascript" src="js/glquicksearch.js"></script>
+[% END %]
index cb7231c..5e6fcf0 100644 (file)
@@ -20,6 +20,9 @@ $(clockon);
     [<a href="login.pl?action=company_logo" target="_blank">[% 'new Window' | $T8 %]</a>]
     [<a href="JavaScript:top.print()">[% 'print' | $T8 %]</a>]
     [[% 'Search contacts' | $T8 %] <input size="15" name="search_term" id="search_term" onkeydown="return on_keydown_quicksearch($('#search_term'), event)">]
+[%- IF AUTH.assert('general_ledger', 1) %]
+    [[% 'GL search' | $T8 %]: <input id="glquicksearch" name="glquicksearch" type="text" class="ui-widget" size="20" maxlength="20">]
+[%- END %]
  </span>
  <span class="frame-header-element frame-header-right">
     [[% 'User' | $T8 %]: [% MYCONFIG.login | html %] -
@@ -38,3 +41,6 @@ $(clockon);
 
  </div>
  <div style="clear: both;"></div>
+[% IF AUTH.assert('general_ledger', 1) %]
+ <script type="text/javascript" src="js/glquicksearch.js"></script>
+[% END %]