]> Frank Brehm's Git Trees - books.git/commitdiff
Aus Util::Book mach Plugin::Book
authorFrank Brehm <frank@brehm-online.com>
Thu, 18 Feb 2010 22:26:57 +0000 (22:26 +0000)
committerFrank Brehm <frank@brehm-online.com>
Thu, 18 Feb 2010 22:26:57 +0000 (22:26 +0000)
lib/FrBr/Books.pm
lib/FrBr/Books/Controller/Books.pm
lib/FrBr/Books/Controller/Serie.pm
lib/FrBr/Books/Plugin/Book.pm [new file with mode: 0644]
lib/FrBr/Books/Util/Book.pm [deleted file]

index e3f677d0dd1f9a6396714b6263b611558287a52e..c19576591f87984243feaf6d6b52c84e1604904c 100644 (file)
@@ -42,6 +42,7 @@ use Catalyst qw/
 
     +FrBr::Books::Plugin::Author
     +FrBr::Books::Plugin::Bindungsart
+    +FrBr::Books::Plugin::Book
     +FrBr::Books::Plugin::BookAdd
     +FrBr::Books::Plugin::Category
     +FrBr::Books::Plugin::Ort
@@ -52,7 +53,7 @@ use Catalyst qw/
 
 /;
 
-our $VERSION = '0.3';
+our $VERSION = '0.4';
 {
     my ($rev) = '$Revision$' =~ /(\d+)/;
     $VERSION = sprintf( $VERSION . ".%d", $rev );
index 9e5e01700dd85d979537cb8d4449bf94999481ca..a5adb8ff85cdfec9b930bc2beb563b8090d1a70e 100644 (file)
@@ -8,7 +8,6 @@ use warnings;
 use base 'Catalyst::Controller';
 
 use FrBr::Common;
-use FrBr::Books::Util::Book;
 
 =head1 NAME
 
@@ -173,7 +172,7 @@ sub list : Local {
        };
        $list_params->{'filter'} = $c->session->{'booklist_filter'} if $c->session->{'booklist_filter'};
        
-    my ( $buchliste, $anzahl ) = get_booklist( $c, $list_params  );
+    my ( $buchliste, $anzahl ) = $c->b_get_booklist( $list_params  );
     my $max_page = 1;
     if ( $anzahl ) {
         $max_page = int( $anzahl / $list_length ) + 1;
@@ -366,7 +365,7 @@ sub sorting : Local {
         'name' => "Sortierung"
     };
 
-    my $columns = get_booklist_sort_columns();
+    my $columns = $c->b_get_booklist_sort_columns();
 
     $c->stash->{'booklist_sort_kriterien'} = [];
     $c->stash->{'booklist_sort_namen'}     = {};
@@ -560,7 +559,7 @@ sub form_view : Path('view') {
         return 1;
     }
 
-    my $buchliste = get_booklist( $c, 'buch_id' => $buch_id );
+    my $buchliste = $c->b_get_booklist( 'buch_id' => $buch_id );
     $c->log->debug( get_output_string( $K, "Erhaltene Buchliste: ", $buchliste ) ) if $c->stash->{'debug_level'} >= 2;
 
     unless ( $buchliste and scalar( @$buchliste ) ) {
@@ -615,7 +614,7 @@ sub delete_buch : Path('delete') {
     }
     $c->session->{'delete_book_id'} = $buch_id;
 
-    my $buchliste = get_booklist( $c, 'buch_id' => $buch_id );
+    my $buchliste = $c->b_get_booklist( 'buch_id' => $buch_id );
     $c->log->debug( get_output_string( $K, "Erhaltene Buchliste: ", $buchliste ) ) if $c->stash->{'debug_level'} >= 2;
 
     unless ( $buchliste and scalar( @$buchliste ) ) {
@@ -634,7 +633,7 @@ sub delete_buch : Path('delete') {
 
     if ( $c->request->params->{'really_delete_book'} and $c->request->params->{'really_delete_book'} eq 'yes' and $c->request->params->{'do_delete'} ) {
         eval {
-            delete_book( $c, $buch_id );
+            $c->b_delete_book( $buch_id );
         };
         if ( $@ ) {
             $c->stash->{'error_message'} = $@;
@@ -695,7 +694,7 @@ sub form_edit : Path('edit') {
     }
 
     # Angaben zum Buch aus der Datenbank holen
-    my $buchliste = get_booklist( $c, 'buch_id' => $buch_id );
+    my $buchliste = $c->b_get_booklist( 'buch_id' => $buch_id );
 
     unless ( $buchliste and scalar( @$buchliste ) ) {
         $c->stash->{'template'} = 'error.tt2';
@@ -775,7 +774,7 @@ sub do_save_book : Private {
     my $book_id = undef;
 
     eval {
-        $book_id = save_book( $c, $book );
+        $book_id = $c->b_save_book( $book );
     };
     if ( $@ ) {
         $c->stash->{'error_message'} = $@;
index eb47664bf4b983d786934ec8fba1742e1b5cf4f4..d49c436628cf2dc99495d78fc3b6e2f4b87f5965 100644 (file)
@@ -8,7 +8,6 @@ use warnings;
 use base 'Catalyst::Controller';
 
 use FrBr::Common;
-use FrBr::Books::Util::Book;
 
 =head1 NAME
 
@@ -431,7 +430,7 @@ sub prepare_data_structures : Private {
     my $K = ( caller(0) )[3] . "(): ";
 
     # Liste aller Bücher zusammensammeln
-    my $buchliste = get_booklist( $c, { 'short_author' => 1, 'sort_criteria' => [ 'title', 'autoren' ], } );
+    my $buchliste = $c->b_get_booklist( { 'short_author' => 1, 'sort_criteria' => [ 'title', 'autoren' ], } );
 
     $c->stash->{'book_list'} = {};
     $c->stash->{'book_array_sorted'} = [];
diff --git a/lib/FrBr/Books/Plugin/Book.pm b/lib/FrBr/Books/Plugin/Book.pm
new file mode 100644 (file)
index 0000000..b910d94
--- /dev/null
@@ -0,0 +1,1082 @@
+package FrBr::Books::Plugin::Book;
+
+# $Id$
+# $URL$
+
+use strict;
+use warnings;
+
+use Carp qw/croak/;
+use Readonly;
+use FrBr::Common;
+
+our $VERSION = '0.2';
+{
+    my ($rev) = '$Revision$' =~ /(\d+)/;
+    $VERSION = sprintf( $VERSION . ".%d", $rev );
+}
+
+#-----------------------------------------------------------------------------------
+
+=head1 NAME
+
+FrBr::Books::Plugin::Book - Plugin-Modul fuer Funktionen rund ums Buch
+
+=head1 METHODS
+
+=cut
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_get_booklist( $params )
+
+Sammelt alle Buecher zusammen.
+
+Folgende benannte Parameter koennen ueber $params uebergeben werden:
+
+=over 4
+
+=item I<buch_id>: Die ID eines konkreten Buches
+
+=item I<title>: Ein konkreter Buchtitel (auch SQL-Metazeichen erlaubt)
+
+=item I<title_original>: Ein konkreter Original-Buchtitel (auch SQL-Metazeichen erlaubt)
+
+(Hinweis: wenn sowohl 'title' als auch 'title_original' uebergeben werden, werden diese ODER-verknuepft)
+
+=item I<autor_id>: Alle Buecher des Autors mit dieser Id
+
+=item I<page>: Die Nummer der Listenseite, die dargestellt werden soll.
+
+Wenn nicht übergeben, werden alle Buecher des Resultsets zurueckgegeben.
+
+=item I<list_length>: Laenge einer Listenseite.
+
+Ist standardmaessig 20. Wird nicht beruecksichtigt, wenn I<page> nicht mit uebergeben wurde.
+
+=item I<short_author>: bool - Autor in Kurzfassung
+
+=item I<filter>: eine optionale Hash-Ref mit folgenden Filterkriterien:
+
+
+
+=item I<sort_criteria>: Eine Array-Ref mit den Spalten, nach denen sortiert wird.
+
+In diesem Fall wird anhand dieses Parameters und nicht des Sitzungsparameters 'book_order_criteria' sortiert
+(Siehe L<b_collect_sort_criteria>).
+
+=back
+
+Rueckgabe: Eine Array-Ref mit allen Buchtiteln, die den uebergebenen Suchkriterien entsprechen.
+
+  $list = [
+    {
+    'ausgabejahr' => '2003',
+    'autor_ids' => [
+      '5'
+    ],
+    'autoren' => [
+      'Bill Napier'
+    ],
+    'bindungsart' => 'Softcover (Taschenbuch)',
+    'bindungsart_id' => '4',
+    'buch_nr' => '093314',
+    'druckjahr' => '2007',
+    'id' => '5',
+    'isbn' => undef,
+    'kategorie_ids' => [
+      '4'
+    ],
+    'kategorien' => [
+      'Mystery-Thriller'
+    ],
+    'kurzinhalt' => 'Bla bla bla, tolles Buch',
+    'ort_beschreibung' => undef,
+    'ort_ist_statisch' => undef,
+    'orts_id' => undef,
+    'ortsname' => undef,
+    'preis' => '7.45',
+    'seiten' => '416',
+    'serien' => [],
+    'serien_ids' => [],
+    'title' => 'Der 77. Grad',
+    'title_original' => 'Shattered Icon',
+    'umrechnung_in_euro' => '1',
+    'untertitel' => undef,
+    'verlags_id' => '3',
+    'verlagsname_long' => 'Bertelsmann Club GmbH - Taschenbuch',
+    'verlagsname_short' => 'Club Taschenbuch',
+    'waehrungs_id' => '1',
+    'waehrungs_kuerzel' => '€',
+    'waehrungs_name' => 'Euro'
+  },
+  ...
+  ];
+
+=cut
+
+sub b_get_booklist {
+
+    my $c = shift;
+    my $K  = ( caller(0) )[3] . "(): ";
+
+    $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2;
+
+    my $params = {};
+    if ( ref($_[0]) and ref($_[0]) eq 'HASH' ) {
+        $params = $_[0];
+    }
+    else {
+        %$params = @_;
+    }
+    $c->log->debug(  get_output_string( $K, "Uebergebene Parameter: ", $params ) ) if $c->stash->{'debug_level'} >= 2;
+
+    my $list = [];
+    my $anzahl_buecher = 0;
+
+    my $storage = $c->model('Schema')->storage;
+
+    my $short_author = $params->{'short_author'} ? 1 : undef;
+
+    # Such- und Sortierparameter zusammensammeln
+    my $b_search_params = {};
+    my $order = undef;
+    if ( $params->{'sort_criteria'} and ref($params->{'sort_criteria'}) and ref($params->{'sort_criteria'}) eq 'ARRAY' ) {
+        $order = $params->{'sort_criteria'};
+    } 
+
+    if ( $params->{'buch_id'} ) {
+        $b_search_params->{'me.id'} = $params->{'buch_id'};
+        $order = undef;
+    }
+    else {
+        $order = $c->b_collect_sort_criteria( $order )
+    }
+
+    # uebergebenen Filter auswerten
+    if ( $params->{'filter'} and ref($params->{'filter'}) and ( scalar( keys %{$params->{'filter'}} ) ) and not $params->{'buch_id'} ) {
+
+        my $filter = $params->{'filter'};
+
+        # Es wurde ein Buchtitel als Filter uebergeben
+        if ( $filter->{'title_name'} ) {
+            if ( $filter->{'title_name_where'} eq 'contains' ) {
+                $b_search_params->{'-or'} = [
+                    'title'          => { 'RLIKE', $filter->{'title_name'} },
+                    'title_original' => { 'RLIKE', $filter->{'title_name'} },
+                    'untertitel'     => { 'RLIKE', $filter->{'title_name'} },
+                ];
+            }
+            elsif ( $filter->{'title_name_where'} eq 'starts_with' ) {
+                $b_search_params->{'-or'} = [
+                    'title'          => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
+                    'title_original' => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
+                    'untertitel'     => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
+                ];
+            }
+            else {
+                $b_search_params->{'-or'} = [
+                    'title'          => $filter->{'title_name'},
+                    'title_original' => $filter->{'title_name'},
+                    'untertitel'     => $filter->{'title_name'},
+                ];
+            }
+        }
+
+        my $buch_id = {};
+
+        # Es wurden Autoren als Filter uebergeben
+        if ( $filter->{'autoren'} and scalar( keys %{ $filter->{'autoren'} } ) ) {
+            my $ids = [ keys( %{ $filter->{'autoren'} } ) ];
+            my $s_params = {};
+            if ( scalar(@$ids) > 1 ) {
+                $s_params->{'me.autor_id'} = { '-in' => $ids };
+            }
+            else {
+                $s_params->{'me.autor_id'} = $ids->[0];
+            }
+            for my $autor ( $c->model('Schema::Autor2buch')->search( $s_params )->all() ) {
+                my $id = $autor->get_column('buch_id');
+                $buch_id->{$id} = 1;
+            }
+        }
+
+        # Es wurden Kategorien als Filter uebergeben
+        if ( $filter->{'kategorien'} and scalar( keys %{ $filter->{'kategorien'} } ) ) {
+            my $ids = [ keys( %{ $filter->{'kategorien'} } ) ];
+            my $s_params = {};
+            if ( scalar(@$ids) > 1 ) {
+                $s_params->{'me.kategorie_id'} = { '-in' => $ids };
+            }
+            else {
+                $s_params->{'me.kategorie_id'} = $ids->[0];
+            }
+            for my $bkat ( $c->model('Schema::Buch2kategorie')->search( $s_params )->all() ) {
+                my $id = $bkat->get_column('buch_id');
+                $buch_id->{$id} = 1;
+            }
+        }
+
+        # Es wurden Buchserien als Filter uebergeben
+        if ( $filter->{'serien'} and scalar( keys %{ $filter->{'serien'} } ) ) {
+            my $ids = [ keys( %{ $filter->{'serien'} } ) ];
+            my $s_params = {};
+            if ( scalar(@$ids) > 1 ) {
+                $s_params->{'me.serien_id'} = { '-in' => $ids };
+            }
+            else {
+                $s_params->{'me.serien_id'} = $ids->[0];
+            }
+            for my $bserie ( $c->model('Schema::Buch2serie')->search( $s_params )->all() ) {
+                my $id = $bserie->get_column('buch_id');
+                $buch_id->{$id} = 1;
+            }
+        }
+
+        # eventuell spezifizierte Buch-Ids auswerten
+        my $buch_ids = undef;
+        if ( keys %$buch_id and scalar( keys %$buch_id ) ) {
+            $buch_ids = [ keys %$buch_id ];
+        }
+        $b_search_params->{'me.id'} = ( scalar(@$buch_ids) > 1 ? { '-in' => $buch_ids } : $buch_ids->[0] ) if $buch_ids;
+
+        # Es wurden Verlage als Filter uebergeben
+        if ( $filter->{'verlage'} and scalar( keys %{ $filter->{'verlage'} } ) ) {
+            my $ids = [ keys( %{ $filter->{'verlage'} } ) ];
+            if ( scalar(@$ids) > 1 ) {
+                $b_search_params->{'me.verlags_id'} = { '-in' => $ids };
+            }
+            else {
+                $b_search_params->{'me.verlags_id'} = $ids->[0];
+            }
+        }
+
+        # Es wurden Aufbewahrungsorte als Filter uebergeben
+        if ( $filter->{'orte'} and scalar( keys %{ $filter->{'orte'} } ) ) {
+            my $ids = [ keys( %{ $filter->{'orte'} } ) ];
+            if ( scalar(@$ids) > 1 ) {
+                if ( exists $filter->{'orte'}{-1} ) {
+                    my $or = [];
+                    push @$or, 'me.orts_id' => \'IS NULL';
+                    #delete $filter->{'orte'}{-1};
+                    my $oids = [ grep { $_ >= 0 } keys %{ $filter->{'orte'} } ];
+                    if ( scalar(@$oids) > 1 ) {
+                        push @$or, 'me.orts_id' => { '-in' => $oids };
+                    }
+                    else {
+                        push @$or, 'me.orts_id' => $oids->[0];
+                    }
+                    $b_search_params->{'-or'} = $or;
+                }
+                else {
+                    $b_search_params->{'me.orts_id'} = { '-in' => $ids };
+                }
+            }
+            else {
+                my $oid = $ids->[0];
+                if ( $oid == -1 ) {
+                    $b_search_params->{'me.orts_id'} = \'IS NULL';
+                }
+                else {
+                    $b_search_params->{'me.orts_id'} = $oid;
+                }
+            }
+        }
+
+    }
+
+    # Suchparameter auf undef setzen, falls es keine gibt.
+    $b_search_params = undef unless scalar keys %$b_search_params;
+    $c->log->debug(  get_output_string( $K, "Suchparameter: ", $b_search_params ) ) if $c->stash->{'debug_level'} >= 2;
+
+    # Anzahl der Buecher insgesamt (ohne paginierung) ermitteln
+    my $other_params = {};
+    $other_params->{'order_by'} = $order;
+    $other_params->{'select'} = [ 'me.id' ];
+    $other_params->{'as'}     = [ 'id' ];
+
+    $anzahl_buecher = $c->model('Schema::BuchListe')->count( $b_search_params, $other_params );
+    $c->log->debug(  get_output_string( $K, "Anzahl gefundene Buecher: ", $anzahl_buecher ) ) if $c->stash->{'debug_level'} >= 2;
+
+       my $page = to_int( $params->{'page'} ) ? to_int( $params->{'page'} ) : undef;
+       my $rows = undef;
+       $rows = ( $params->{'list_length'} || $c->stash->{'list_length'} || 20 ) if defined $page;
+
+       if ( $page ) {
+               $other_params->{'rows'} = $rows;
+               $other_params->{'page'} = $page;
+       }
+    my $book_ids = [];
+
+    for my $book ( $c->model('Schema::BuchListe')->search( $b_search_params, $other_params )->all() ) {
+        push @$book_ids, $book->get_column('id');
+    }
+
+    return ( wantarray ? ( $book_ids, 0 ) : $book_ids ) unless scalar( @$book_ids );
+
+    my $in = "IN ( " . join( ", ", @$book_ids ) . " )";
+
+    $b_search_params = { 'me.id' => \$in };
+
+    $other_params = {};
+    $other_params->{'join'}     = [ 'waehrung', 'verlag', 'ort', 'bindungsart' ];
+    $other_params->{'select'} = [
+        'me.id',
+        'me.title',
+        'me.title_original',
+        'me.untertitel',
+        'me.bindungsart_id',
+        'bindungsart.art_name',
+        'me.verlags_id',
+        'me.orts_id',
+        'me.isbn',
+        'me.buch_nr',
+        'me.ausgabejahr',
+        'me.druckjahr',
+        'me.seiten',
+        'me.kurzinhalt',
+        'me.preis',
+        'me.waehrungs_id',
+        'waehrung.waehrungs_kuerzel',
+        'waehrung.waehrungs_name',
+        'waehrung.umrechnung_in_euro',
+        'verlag.name_short',
+        'verlag.name_long',
+        'ort.name',
+        'ort.descr',
+        'ort.statisch',
+    ];
+    $other_params->{'as'} = [
+        'id',
+        'title',
+        'title_original',
+        'untertitel',
+        'bindungsart_id',
+        'bindungsart',
+        'verlags_id',
+        'orts_id',
+        'isbn',
+        'buch_nr',
+        'ausgabejahr',
+        'druckjahr',
+        'seiten',
+        'kurzinhalt',
+        'preis',
+        'waehrungs_id',
+        'waehrungs_kuerzel',
+        'waehrungs_name',
+        'umrechnung_in_euro',
+        'verlagsname_short',
+        'verlagsname_long',
+        'ortsname',
+        'ort_beschreibung',
+        'ort_ist_statisch',
+    ];
+    my $buchmap = {};
+    for my $book ( $c->model('Schema::Buecher')->search( $b_search_params, $other_params )->all() ) {
+        my $buch = {};
+        my $id                        = $book->id();
+        $buch->{'id'}                 = $id;
+        $buch->{'title'}              = $book->title();
+        $buch->{'title_original'}     = $book->title_original();
+        $buch->{'untertitel'}         = $book->untertitel();
+        $buch->{'bindungsart_id'}     = $book->bindungsart_id();
+        $buch->{'bindungsart'}        = $book->get_column('bindungsart');
+        $buch->{'verlags_id'}         = $book->verlags_id();
+        $buch->{'orts_id'}            = $book->orts_id();
+        $buch->{'isbn'}               = $book->isbn();
+        $buch->{'buch_nr'}            = $book->buch_nr();
+        $buch->{'ausgabejahr'}        = $book->ausgabejahr();
+        $buch->{'druckjahr'}          = $book->druckjahr();
+        $buch->{'seiten'}             = $book->seiten();
+        $buch->{'kurzinhalt'}         = $book->kurzinhalt();
+        $buch->{'preis'}              = $book->preis();
+        $buch->{'waehrungs_id'}       = $book->waehrungs_id();
+        $buch->{'waehrungs_kuerzel'}  = $book->get_column('waehrungs_kuerzel');
+        $buch->{'waehrungs_name'}     = $book->get_column('waehrungs_name');
+        $buch->{'umrechnung_in_euro'} = $book->get_column('umrechnung_in_euro');
+        $buch->{'verlagsname_short'}  = $book->get_column('verlagsname_short');
+        $buch->{'verlagsname_long'}   = $book->get_column('verlagsname_long');
+        $buch->{'ortsname'}           = $book->get_column('ortsname');
+        $buch->{'ort_beschreibung'}   = $book->get_column('ort_beschreibung');
+        $buch->{'ort_ist_statisch'}   = $book->get_column('ort_ist_statisch');
+        $buch->{'autoren'}            = [];
+        $buch->{'autor_ids'}          = [];
+        $buch->{'kategorien'}         = [];
+        $buch->{'kategorie_ids'}      = [];
+        $buch->{'serien'}             = [];
+        $buch->{'serien_ids'}         = [];
+        $buchmap->{$id} = $buch;
+    }
+
+    # Autoren zusammensammeln
+    my $a_search_params = {};
+    $a_search_params->{'buch_id'} = \$in;
+
+    $other_params = {};
+    $other_params->{'order_by'} = [ 'ord_num' ];
+    $other_params->{'join'}     = [ 'autor' ];
+    $other_params->{'select'} = [
+        'me.buch_id',
+        'autor.id',
+        'autor.titel',
+        'autor.vorname',
+        'autor.mittelname',
+        'autor.nachname',
+        'autor.name_suffix',
+    ];
+    $other_params->{'as'} = [
+        'buch_id',
+        'autor_id',
+        'titel',
+        'vorname',
+        'mittelname',
+        'nachname',
+        'name_suffix',
+    ];
+    for my $ref ( $c->model('Schema::Autor2buch')->search( $a_search_params, $other_params )->all() ) {
+        my $bid = $ref->get_column('buch_id');
+        my $aid = $ref->get_column('autor_id');
+        my @N;
+        if ( $short_author ) {
+            my $n;
+            if ( $ref->get_column('vorname') ) {
+                $n = substr( $ref->get_column('vorname'), 0, 1 );
+                $n .= ".";
+                push @N, $n;
+            }
+            if ( $ref->get_column('mittelname') ) {
+                $n = substr( $ref->get_column('mittelname'), 0, 1 );
+                $n .= ".";
+                push @N, $n;
+            }
+        }
+        else {
+            push @N, $ref->get_column('titel') if $ref->get_column('titel');
+            push @N, $ref->get_column('vorname') if $ref->get_column('vorname');
+            push @N, $ref->get_column('mittelname') if $ref->get_column('mittelname');
+        }
+        push @N, $ref->get_column('nachname');
+        push @N, $ref->get_column('name_suffix') if $ref->get_column('name_suffix');
+        my $autor = join( " ", @N );
+        push @{ $buchmap->{$bid}{'autoren'} },   $autor;
+        push @{ $buchmap->{$bid}{'autor_ids'} }, $aid;
+    }
+
+    # Kategorien zusammensammeln
+    delete $other_params->{'order_by'} if exists $other_params->{'order_by'};
+    $other_params->{'join'} = [ 'kategorie' ];
+    $other_params->{'select'} = [
+        'me.buch_id',
+        'kategorie.id',
+        'kategorie.kategorie_name',
+    ];
+    $other_params->{'as'} = [
+        'buch_id',
+        'kategorie_id',
+        'kategorie_name',
+    ];
+    for my $ref ( $c->model('Schema::Buch2kategorie')->search( $a_search_params, $other_params )->all() ) {
+        my $bid  = $ref->get_column('buch_id');
+        my $kid  = $ref->get_column('kategorie_id');
+        my $name = $ref->get_column('kategorie_name');
+        push @{ $buchmap->{$bid}{'kategorien'} },    $name;
+        push @{ $buchmap->{$bid}{'kategorie_ids'} }, $kid;
+    }
+
+    # Buchserien zusammensammeln
+    delete $other_params->{'order_by'} if exists $other_params->{'order_by'};
+    $other_params->{'join'} = [ 'serie' ];
+    $other_params->{'select'} = [
+        'me.buch_id',
+        'serie.id',
+        'serie.serien_name',
+    ];
+    $other_params->{'as'} = [
+        'buch_id',
+        'serien_id',
+        'serien_name',
+    ];
+    for my $ref ( $c->model('Schema::Buch2serie')->search( $a_search_params, $other_params )->all() ) {
+        my $bid  = $ref->get_column('buch_id');
+        my $sid  = $ref->get_column('serien_id');
+        my $name = $ref->get_column('serien_name');
+        push @{ $buchmap->{$bid}{'serien'} },     $name;
+        push @{ $buchmap->{$bid}{'serien_ids'} }, $sid;
+    }
+
+    # HashRef %$buchmap sortiert in ArrayRef $list ummappen
+
+    for my $id ( @$book_ids ) {
+        push @$list, $buchmap->{$id} if $buchmap->{$id};
+    }
+
+    return ( wantarray ? ( $list, $anzahl_buecher ) : $list );
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_get_booklist_sort_columns( )
+
+Gibt eine Hash-Ref mit allen verfügbaren Spaltennamen zurück, nach denen
+die Bücherliste sortiert werden kann.
+
+=cut
+
+sub b_get_booklist_sort_columns {
+
+    my $c = shift;
+
+    Readonly::Scalar my $valid_columns => {
+        'autoren'        => 'Autor/-en',
+        'title'          => 'Buchtitel',
+        'title_original' => 'Original Buchtitel',
+        'bindungsart'    => 'Bindungsart',
+        'verlag'         => 'Buchverlag',
+        'ort'            => 'Aufbewahrungsort',
+        'preis'          => 'Preis',
+        'waehrung'       => 'Währung des Buchpreises',
+        'ausgabejahr'    => 'Ausgabejahr',
+        'druckjahr'      => 'Druckjahr',
+        'seiten'         => 'Seitenzahl',
+        'kategorien'     => 'Buchketagorie(-n)',
+        'serien'         => 'Zyklus/Reihe',
+    };
+
+    return $valid_columns;
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_collect_sort_criteria( [ $criteria ] )
+
+Sammelt aus der Sitzung die Sortierkriterien der Buchliste zusammen und gibt diese verwendbar
+für b_get_booklist() zurück.
+
+Die Sortierkriterien müssen in der Sitzung unter dem Schlüssel 'book_order_criteria'
+als Array-Ref abgelegt sein. Die Elemente der Array-Ref sind entweder Scalare mit den
+Spaltennamen oder Hashrefs der Form [ { 'autoren' => 'desc' }, { 'kategorien' => 'asc' }, ...].
+
+Es kann auch als weiterer Parameter eine Array-Ref mit den Sorierkriterien uebergeben werden.
+In diesem Fall wird der Sitzungsschluessel 'book_order_criteria' nicht beruecksichtigt.
+
+Folgende Spaltennamen dürfen verwendet werden:
+
+  - autoren
+  - title
+  - title_original
+  - bindungsart
+  - verlag
+  - ort
+  - preis
+  - waehrung
+  - ausgabejahr
+  - druckjahr
+  - seiten
+  - kategorien
+  - serien
+
+Falls in $c->session->{'book_order_criteria'} nichts liegt, wird folgendes
+als Voreinstellung verwendet:
+
+    $criteria = [
+        'autoren',
+        'title',
+    ];
+
+=cut
+
+sub b_collect_sort_criteria {
+
+    my $c = shift;
+    my $K = ( caller(0) )[3] . "(): ";
+
+    my $given_criteria = shift;
+
+    my $order = [];
+
+    my $valid_column = $c->b_get_booklist_sort_columns();
+
+    my $used_column = {};
+
+    $given_criteria = undef unless ( $given_criteria and ref($given_criteria) and ref($given_criteria) eq 'ARRAY' );
+
+    my $criteria = ( $given_criteria or $c->session->{'book_order_criteria'} );
+    unless ( $criteria and ref($criteria) and ref($criteria) eq 'ARRAY' and scalar(@$criteria) ) {
+        $criteria = [
+            'autoren',
+            'title',
+        ];
+    }
+
+    my $col;
+    for my $crit ( @$criteria ) {
+        if ( ref($crit) and ref($crit) eq 'HASH' ) {
+            for my $key ( keys %$crit ) {
+                $col = lc($key);
+                if ( $valid_column->{$col} and not exists $used_column->{$col} ) {
+                    my $dir = $crit->{$key};
+                    $dir = ( $dir =~ /desc/i ) ? 'DESC' : 'ASC';
+                    $used_column->{$col} = 1;
+                    push @$order, ( $dir eq 'ASC' ? $col : \"`$col` DESC" );
+                }
+            }
+        }
+        else {
+            $col = lc($crit);
+            if ( $valid_column->{$col} and not exists $used_column->{$col} ) {
+                push @$order, $col;
+                $used_column->{$col} = 1;
+            }
+        }
+    }
+
+    $order = [ 'title' ] unless scalar( @$order );
+
+    return $order;
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_delete_book( $book_id )
+
+Loescht das Buch mit der uebergebenen Buch-Id
+
+=cut
+
+sub b_delete_book {
+
+    my $c       = shift;
+    my $book_id = shift;
+    my $K       = ( caller(0) )[3] . "(): ";
+
+    $c->log->debug( $K . "aufgerufen fuer Buch-Id " . ( defined $book_id ? $book_id : '<undef>' ) . "." ) if $c->stash->{'debug_level'} > 2;
+
+    return undef unless $book_id and to_int($book_id);
+    $book_id = to_int($book_id);
+
+    my $schema =  $c->model('Schema')->{'schema'};
+    #$c->log->debug( get_output_string( $K . "Schema: ", $schema ) ) if $c->stash->{'debug_level'} > 4;
+    my $search_params = {
+        'buch_id' => $book_id,
+    };
+
+    my $coderef = sub {
+        $c->model('Schema::Autor2buch')->search( $search_params )->delete();
+        $c->model('Schema::Buch2kategorie')->search( $search_params )->delete();
+        $c->model('Schema::Buch2serie')->search( $search_params )->delete();
+        $c->model('Schema::Buecher')->search( { 'id' => $book_id } )->delete();
+    };
+
+    my $rs;
+    eval {
+        $rs = $schema->txn_do($coderef);
+    };
+
+    if ($@) {                             # Transaction failed
+        die "Rollback nicht erfolgreich!" if ($@ =~ /Rollback failed/i );     # Rollback failed
+        die $@;
+    }
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_save_book( $book )
+
+  $book = {
+    'ausgabejahr' => '2004',
+    'autoren' => [
+      '11'
+    ],
+    'bindungsart_id' => 4,
+    'book_nr' => '',
+    'druckjahr' => '2006',
+    'isbn' => '3-492-70076-4',
+    'kategorien' => [
+      '2'
+    ],
+    'kurzinhalt' => 'bla bla bla',
+    'original_title' => '',
+    'orts_id' => '2',
+    'preis' => 14,
+    'seiten' => '640',
+    'serien' => [
+      '4'
+    ],
+    'title' => 'Die Zwerge',
+    'untertitel' => '',
+    'verlags_id' => '8',
+    'waehrungs_id' => '1'
+  };
+
+=cut
+
+sub b_save_book {
+
+    my $c    = shift;
+    my $book = shift;
+    my $K    = ( caller(0) )[3] . "(): ";
+
+    $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2;
+
+    my $storage = $c->model('Schema')->storage;
+
+    my $tmp = $book->{'kurzinhalt'};
+    $tmp = '' unless defined $tmp;
+    $tmp =~ s/^\s+//;
+    $tmp =~ s/\s+$//;
+       $book->{'kurzinhalt'} = $tmp eq '' ? undef : $tmp;
+
+    my $save_func = sub {
+
+        my $storage = shift;
+        my $dbh     = shift;
+        my $buch    = shift;
+
+        my $sql = <<ENDE;
+INSERT INTO `buecher` (
+    `id`, `title`, `title_original`, `untertitel`, `verlags_id`, `orts_id`, `kurzinhalt`,
+    `bindungsart_id`, `isbn`, `buch_nr`, `ausgabejahr`, `druckjahr`, `seiten`, `preis`, `waehrungs_id` )
+  VALUES (
+    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+  ON DUPLICATE KEY UPDATE
+    `id`             = LAST_INSERT_ID(`id`),
+    `title`          = ?,
+    `title_original` = ?,
+    `untertitel`     = ?,
+    `verlags_id`     = ?,
+    `orts_id`        = ?,
+    `kurzinhalt`     = ?,
+    `bindungsart_id` = ?,
+    `isbn`           = ?,
+    `buch_nr`        = ?,
+    `ausgabejahr`    = ?,
+    `druckjahr`      = ?,
+    `seiten`         = ?,
+    `preis`          = ?,
+    `waehrungs_id`   = ?
+ENDE
+
+        my @params = ();
+        push @params, $buch->{'id'};
+        push @params, $buch->{'title'};
+        push @params, $buch->{'original_title'};
+        push @params, $buch->{'untertitel'};
+        push @params, $buch->{'verlags_id'};
+        push @params, $buch->{'orts_id'};
+        push @params, $buch->{'kurzinhalt'};
+        push @params, $buch->{'bindungsart_id'};
+        push @params, $buch->{'isbn'};
+        push @params, $buch->{'book_nr'};
+        push @params, $buch->{'ausgabejahr'};
+        push @params, $buch->{'druckjahr'};
+        push @params, $buch->{'seiten'};
+        push @params, $buch->{'preis'};
+        push @params, $buch->{'waehrungs_id'};
+
+        push @params, $buch->{'title'};
+        push @params, $buch->{'original_title'};
+        push @params, $buch->{'untertitel'};
+        push @params, $buch->{'verlags_id'};
+        push @params, $buch->{'orts_id'};
+        push @params, $buch->{'kurzinhalt'};
+        push @params, $buch->{'bindungsart_id'};
+        push @params, $buch->{'isbn'};
+        push @params, $buch->{'book_nr'};
+        push @params, $buch->{'ausgabejahr'};
+        push @params, $buch->{'druckjahr'};
+        push @params, $buch->{'seiten'};
+        push @params, $buch->{'preis'};
+        push @params, $buch->{'waehrungs_id'};
+
+        if ( $storage->debug() ) {
+            my $text = $sql;
+            $text =~ s/\s+$//;
+            $text .= ": " . join( ", ", map { $dbh->quote($_) } @params ) . "\n";
+            warn $text;
+        }
+
+        my $sth = $dbh->prepare($sql);
+        $sth->execute( @params );
+
+    };
+
+    $storage->dbh_do( $save_func, $book );
+
+    my $book_id = $storage->last_insert_id();
+
+    return undef unless $book_id;
+
+    $c->b_save_buch_autoren( $book_id, $book->{'autoren'} );
+    $c->b_save_buch_kategorien( $book_id, $book->{'kategorien'} );
+    $c->b_save_buch_serien( $book_id, $book->{'serien'} );
+
+    return $book_id;
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_save_buch_autoren( $book_id, @$autor_ids )
+
+=cut
+
+sub b_save_buch_autoren {
+
+    my $c         = shift;
+    my $book_id   = shift;
+    my $autor_ids = shift;
+
+    my $K    = ( caller(0) )[3] . "(): ";
+
+    my $storage = $c->model('Schema')->storage;
+    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
+    my $dbh = $storage->dbh();
+    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
+
+    my $anzahl = 0;
+    $anzahl = scalar( @$autor_ids ) if $autor_ids and ref($autor_ids) and ref($autor_ids) eq 'ARRAY';
+
+    my $in = '';
+    $in = '(' . join( ", ", map { $dbh->quote($_) } @$autor_ids ) . ")" if $anzahl;
+
+    my $sql;
+    $sql = <<ENDE;
+DELETE FROM `autor2buch`
+ WHERE `buch_id` = ?
+ENDE
+    $sql .= "   AND `autor_id` NOT IN " . $in . "\n" if $anzahl;
+
+    my $qparams = [];
+    push @$qparams, $book_id;
+
+    if ( $storage->debug() ) {
+        my $text = $sql;
+        $text =~ s/\s+$//;
+        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+        warn $text;
+    }
+
+    my $sth = $dbh->prepare($sql);
+    $sth->execute( @$qparams );
+
+    return 1 unless $anzahl;
+
+    my $i = 0;
+
+    $sql = <<ENDE;
+INSERT INTO `autor2buch` (
+    `buch_id`, `autor_id`, `ord_num`
+  ) VALUES (
+    ?, ?, ? )
+  ON DUPLICATE KEY UPDATE
+    `ord_num` = ?
+ENDE
+
+    $sth = $dbh->prepare($sql);
+
+    for my $autor_id ( @$autor_ids ) {
+
+        $qparams = [];
+        push @$qparams, $book_id;
+        push @$qparams, $autor_id;
+        push @$qparams, $i;
+        push @$qparams, $i;
+
+        if ( $storage->debug() ) {
+            my $text = $sql;
+            $text =~ s/\s+$//;
+            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+            warn $text;
+        }
+
+        $sth->execute( @$qparams );
+
+        $i++;
+    }
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_save_buch_serien( $book_id, @$serien_ids )
+
+=cut
+
+sub b_save_buch_serien {
+
+    my $c          = shift;
+    my $book_id    = shift;
+    my $serien_ids = shift;
+
+    my $K    = ( caller(0) )[3] . "(): ";
+
+    my $storage = $c->model('Schema')->storage;
+    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
+    my $dbh = $storage->dbh();
+    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
+
+    my $anzahl = 0;
+    $anzahl = scalar( @$serien_ids ) if $serien_ids and ref($serien_ids) and ref($serien_ids) eq 'ARRAY';
+
+    my $in = '';
+    $in = '(' . join( ", ", map { $dbh->quote($_) } @$serien_ids ) . ")" if $anzahl;
+
+    my $sql;
+    $sql = <<ENDE;
+DELETE FROM `buch2serie`
+ WHERE `buch_id` = ?
+ENDE
+    $sql .= "   AND `serien_id` NOT IN " . $in . "\n" if $anzahl;
+
+    my $qparams = [];
+    push @$qparams, $book_id;
+
+    if ( $storage->debug() ) {
+        my $text = $sql;
+        $text =~ s/\s+$//;
+        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+        warn $text;
+    }
+
+    my $sth = $dbh->prepare($sql);
+    $sth->execute( @$qparams );
+
+    return 1 unless $anzahl;
+
+    my $i = 1;
+
+    $sql = <<ENDE;
+INSERT INTO `buch2serie` (
+    `buch_id`, `serien_id`, `ord_num`
+  ) VALUES (
+    ?, ?, ? )
+  ON DUPLICATE KEY UPDATE
+    `ord_num` = IFNULL( `ord_num`, ? )
+ENDE
+
+    $sth = $dbh->prepare($sql);
+
+    for my $serien_id ( @$serien_ids ) {
+
+        $qparams = [];
+        push @$qparams, $book_id;
+        push @$qparams, $serien_id;
+        push @$qparams, $i;
+        push @$qparams, $i;
+
+        if ( $storage->debug() ) {
+            my $text = $sql;
+            $text =~ s/\s+$//;
+            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+            warn $text;
+        }
+
+        $sth->execute( @$qparams );
+
+        $i++;
+    }
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head2 $c->b_save_buch_kategorien( $book_id, @$kategorie_ids )
+
+=cut
+
+sub b_save_buch_kategorien {
+
+    my $c             = shift;
+    my $book_id       = shift;
+    my $kategorie_ids = shift;
+
+    my $K    = ( caller(0) )[3] . "(): ";
+
+    my $storage = $c->model('Schema')->storage;
+    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
+    my $dbh = $storage->dbh();
+    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
+
+    my $anzahl = 0;
+    $anzahl = scalar( @$kategorie_ids ) if $kategorie_ids and ref($kategorie_ids) and ref($kategorie_ids) eq 'ARRAY';
+
+    my $in = '';
+    $in = '(' . join( ", ", map { $dbh->quote($_) } @$kategorie_ids ) . ")" if $anzahl;
+
+    my $sql;
+    $sql = <<ENDE;
+DELETE FROM `buch2kategorie`
+ WHERE `buch_id` = ?
+ENDE
+    $sql .= "   AND `kategorie_id` NOT IN " . $in . "\n" if $anzahl;
+
+    my $qparams = [];
+    push @$qparams, $book_id;
+
+    if ( $storage->debug() ) {
+        my $text = $sql;
+        $text =~ s/\s+$//;
+        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+        warn $text;
+    }
+
+    my $sth = $dbh->prepare($sql);
+    $sth->execute( @$qparams );
+
+    return 1 unless $anzahl;
+
+    $sql = <<ENDE;
+INSERT INTO `buch2kategorie` (
+    `buch_id`, `kategorie_id`
+  ) VALUES (
+    ?, ? )
+  ON DUPLICATE KEY UPDATE
+    `kategorie_id` = `kategorie_id`
+ENDE
+
+    $sth = $dbh->prepare($sql);
+
+    for my $kategorie_id ( @$kategorie_ids ) {
+
+        $qparams = [];
+        push @$qparams, $book_id;
+        push @$qparams, $kategorie_id;
+
+        if ( $storage->debug() ) {
+            my $text = $sql;
+            $text =~ s/\s+$//;
+            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
+            warn $text;
+        }
+
+        $sth->execute( @$qparams );
+
+    }
+
+}
+
+#-----------------------------------------------------------------------------------
+
+=head1 AUTHOR
+
+Frank Brehm
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
+
+__END__
+
+# vim: noai : ts=4 fenc=utf-8 filetype=perl expandtab :
diff --git a/lib/FrBr/Books/Util/Book.pm b/lib/FrBr/Books/Util/Book.pm
deleted file mode 100644 (file)
index d09f68d..0000000
+++ /dev/null
@@ -1,1103 +0,0 @@
-package FrBr::Books::Util::Book;
-
-# $Id$
-# $URL$
-
-use strict;
-use warnings;
-
-use Readonly;
-use FrBr::Common;
-
-# Export-Deklarationen
-
-BEGIN {
-
-    use Exporter();
-    our ( $VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS );
-
-    # set the version for version checking
-    $VERSION = 0.1;
-    my ($rev) = '$Revision$' =~ /(\d+)/;
-    $VERSION = sprintf( $VERSION . ".%d", $rev );
-
-    @ISA    = qw(Exporter);
-    @EXPORT = qw(
-        &get_booklist
-        &get_booklist_sort_columns
-        &save_book
-        &delete_book
-    );
-
-    #%EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
-
-    # your exported package globals go here,
-    # as well as any optionally exported functions
-    #@EXPORT_OK   = qw($Var1 %Hashit &func3);
-} ## end BEGIN
-
-our @EXPORT_OK;
-
-=head1 NAME
-
-FrBr::Books::Util::Book - Modul fuer Funktionen rund ums Buch
-
-=head1 METHODS
-
-=cut
-
-#-----------------------------------------------------------------------------------
-
-=head2 get_booklist( $c, $params )
-
-Sammelt alle Buecher zusammen.
-
-Folgende benannte Parameter koennen ueber $params uebergeben werden:
-
-=over 4
-
-=item I<buch_id>: Die ID eines konkreten Buches
-
-=item I<title>: Ein konkreter Buchtitel (auch SQL-Metazeichen erlaubt)
-
-=item I<title_original>: Ein konkreter Original-Buchtitel (auch SQL-Metazeichen erlaubt)
-
-(Hinweis: wenn sowohl 'title' als auch 'title_original' uebergeben werden, werden diese ODER-verknuepft)
-
-=item I<autor_id>: Alle Buecher des Autors mit dieser Id
-
-=item I<page>: Die Nummer der Listenseite, die dargestellt werden soll.
-
-Wenn nicht übergeben, werden alle Buecher des Resultsets zurueckgegeben.
-
-=item I<list_length>: Laenge einer Listenseite.
-
-Ist standardmaessig 20. Wird nicht beruecksichtigt, wenn I<page> nicht mit uebergeben wurde.
-
-=item I<short_author>: bool - Autor in Kurzfassung
-
-=item I<filter>: eine optionale Hash-Ref mit folgenden Filterkriterien:
-
-
-
-=item I<sort_criteria>: Eine Array-Ref mit den Spalten, nach denen sortiert wird.
-
-In diesem Fall wird anhand dieses Parameters und nicht des Sitzungsparameters 'book_order_criteria' sortiert
-(Siehe L<collect_sort_criteria>).
-
-=back
-
-Rueckgabe: Eine Array-Ref mit allen Buchtiteln, die den uebergebenen Suchkriterien entsprechen.
-
-  $list = [
-    {
-    'ausgabejahr' => '2003',
-    'autor_ids' => [
-      '5'
-    ],
-    'autoren' => [
-      'Bill Napier'
-    ],
-    'bindungsart' => 'Softcover (Taschenbuch)',
-    'bindungsart_id' => '4',
-    'buch_nr' => '093314',
-    'druckjahr' => '2007',
-    'id' => '5',
-    'isbn' => undef,
-    'kategorie_ids' => [
-      '4'
-    ],
-    'kategorien' => [
-      'Mystery-Thriller'
-    ],
-    'kurzinhalt' => 'Bla bla bla, tolles Buch',
-    'ort_beschreibung' => undef,
-    'ort_ist_statisch' => undef,
-    'orts_id' => undef,
-    'ortsname' => undef,
-    'preis' => '7.45',
-    'seiten' => '416',
-    'serien' => [],
-    'serien_ids' => [],
-    'title' => 'Der 77. Grad',
-    'title_original' => 'Shattered Icon',
-    'umrechnung_in_euro' => '1',
-    'untertitel' => undef,
-    'verlags_id' => '3',
-    'verlagsname_long' => 'Bertelsmann Club GmbH - Taschenbuch',
-    'verlagsname_short' => 'Club Taschenbuch',
-    'waehrungs_id' => '1',
-    'waehrungs_kuerzel' => '€',
-    'waehrungs_name' => 'Euro'
-  },
-  ...
-  ];
-
-=cut
-
-sub get_booklist {
-
-    my $c = shift;
-    my $K  = ( caller(0) )[3] . "(): ";
-
-    $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2;
-
-    my $params = {};
-    if ( ref($_[0]) and ref($_[0]) eq 'HASH' ) {
-        $params = $_[0];
-    }
-    else {
-        %$params = @_;
-    }
-    $c->log->debug(  get_output_string( $K, "Uebergebene Parameter: ", $params ) ) if $c->stash->{'debug_level'} >= 2;
-
-    my $list = [];
-    my $anzahl_buecher = 0;
-
-    my $storage = $c->stash->{'storage'};
-
-    my $short_author = $params->{'short_author'} ? 1 : undef;
-
-    # Such- und Sortierparameter zusammensammeln
-    my $b_search_params = {};
-    my $order = undef;
-    if ( $params->{'sort_criteria'} and ref($params->{'sort_criteria'}) and ref($params->{'sort_criteria'}) eq 'ARRAY' ) {
-        $order = $params->{'sort_criteria'};
-    } 
-
-    if ( $params->{'buch_id'} ) {
-        $b_search_params->{'me.id'} = $params->{'buch_id'};
-        $order = undef;
-    }
-    else {
-        $order = collect_sort_criteria( $c, $order )
-    }
-
-    # uebergebenen Filter auswerten
-    if ( $params->{'filter'} and ref($params->{'filter'}) and ( scalar( keys %{$params->{'filter'}} ) ) and not $params->{'buch_id'} ) {
-
-        my $filter = $params->{'filter'};
-
-        # Es wurde ein Buchtitel als Filter uebergeben
-        if ( $filter->{'title_name'} ) {
-            if ( $filter->{'title_name_where'} eq 'contains' ) {
-                $b_search_params->{'-or'} = [
-                    'title'          => { 'RLIKE', $filter->{'title_name'} },
-                    'title_original' => { 'RLIKE', $filter->{'title_name'} },
-                    'untertitel'     => { 'RLIKE', $filter->{'title_name'} },
-                ];
-            }
-            elsif ( $filter->{'title_name_where'} eq 'starts_with' ) {
-                $b_search_params->{'-or'} = [
-                    'title'          => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
-                    'title_original' => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
-                    'untertitel'     => { 'LIKE', ( $filter->{'title_name'} . '%' ) },
-                ];
-            }
-            else {
-                $b_search_params->{'-or'} = [
-                    'title'          => $filter->{'title_name'},
-                    'title_original' => $filter->{'title_name'},
-                    'untertitel'     => $filter->{'title_name'},
-                ];
-            }
-        }
-
-        my $buch_id = {};
-
-        # Es wurden Autoren als Filter uebergeben
-        if ( $filter->{'autoren'} and scalar( keys %{ $filter->{'autoren'} } ) ) {
-            my $ids = [ keys( %{ $filter->{'autoren'} } ) ];
-            my $s_params = {};
-            if ( scalar(@$ids) > 1 ) {
-                $s_params->{'me.autor_id'} = { '-in' => $ids };
-            }
-            else {
-                $s_params->{'me.autor_id'} = $ids->[0];
-            }
-            for my $autor ( $c->model('Schema::Autor2buch')->search( $s_params )->all() ) {
-                my $id = $autor->get_column('buch_id');
-                $buch_id->{$id} = 1;
-            }
-        }
-
-        # Es wurden Kategorien als Filter uebergeben
-        if ( $filter->{'kategorien'} and scalar( keys %{ $filter->{'kategorien'} } ) ) {
-            my $ids = [ keys( %{ $filter->{'kategorien'} } ) ];
-            my $s_params = {};
-            if ( scalar(@$ids) > 1 ) {
-                $s_params->{'me.kategorie_id'} = { '-in' => $ids };
-            }
-            else {
-                $s_params->{'me.kategorie_id'} = $ids->[0];
-            }
-            for my $bkat ( $c->model('Schema::Buch2kategorie')->search( $s_params )->all() ) {
-                my $id = $bkat->get_column('buch_id');
-                $buch_id->{$id} = 1;
-            }
-        }
-
-        # Es wurden Buchserien als Filter uebergeben
-        if ( $filter->{'serien'} and scalar( keys %{ $filter->{'serien'} } ) ) {
-            my $ids = [ keys( %{ $filter->{'serien'} } ) ];
-            my $s_params = {};
-            if ( scalar(@$ids) > 1 ) {
-                $s_params->{'me.serien_id'} = { '-in' => $ids };
-            }
-            else {
-                $s_params->{'me.serien_id'} = $ids->[0];
-            }
-            for my $bserie ( $c->model('Schema::Buch2serie')->search( $s_params )->all() ) {
-                my $id = $bserie->get_column('buch_id');
-                $buch_id->{$id} = 1;
-            }
-        }
-
-        # eventuell spezifizierte Buch-Ids auswerten
-        my $buch_ids = undef;
-        if ( keys %$buch_id and scalar( keys %$buch_id ) ) {
-            $buch_ids = [ keys %$buch_id ];
-        }
-        $b_search_params->{'me.id'} = ( scalar(@$buch_ids) > 1 ? { '-in' => $buch_ids } : $buch_ids->[0] ) if $buch_ids;
-
-        # Es wurden Verlage als Filter uebergeben
-        if ( $filter->{'verlage'} and scalar( keys %{ $filter->{'verlage'} } ) ) {
-            my $ids = [ keys( %{ $filter->{'verlage'} } ) ];
-            if ( scalar(@$ids) > 1 ) {
-                $b_search_params->{'me.verlags_id'} = { '-in' => $ids };
-            }
-            else {
-                $b_search_params->{'me.verlags_id'} = $ids->[0];
-            }
-        }
-
-        # Es wurden Aufbewahrungsorte als Filter uebergeben
-        if ( $filter->{'orte'} and scalar( keys %{ $filter->{'orte'} } ) ) {
-            my $ids = [ keys( %{ $filter->{'orte'} } ) ];
-            if ( scalar(@$ids) > 1 ) {
-                if ( exists $filter->{'orte'}{-1} ) {
-                    my $or = [];
-                    push @$or, 'me.orts_id' => \'IS NULL';
-                    #delete $filter->{'orte'}{-1};
-                    my $oids = [ grep { $_ >= 0 } keys %{ $filter->{'orte'} } ];
-                    if ( scalar(@$oids) > 1 ) {
-                        push @$or, 'me.orts_id' => { '-in' => $oids };
-                    }
-                    else {
-                        push @$or, 'me.orts_id' => $oids->[0];
-                    }
-                    $b_search_params->{'-or'} = $or;
-                }
-                else {
-                    $b_search_params->{'me.orts_id'} = { '-in' => $ids };
-                }
-            }
-            else {
-                my $oid = $ids->[0];
-                if ( $oid == -1 ) {
-                    $b_search_params->{'me.orts_id'} = \'IS NULL';
-                }
-                else {
-                    $b_search_params->{'me.orts_id'} = $oid;
-                }
-            }
-        }
-
-    }
-
-    # Suchparameter auf undef setzen, falls es keine gibt.
-    $b_search_params = undef unless scalar keys %$b_search_params;
-    $c->log->debug(  get_output_string( $K, "Suchparameter: ", $b_search_params ) ) if $c->stash->{'debug_level'} >= 2;
-
-    # Anzahl der Buecher insgesamt (ohne paginierung) ermitteln
-    my $other_params = {};
-    $other_params->{'order_by'} = $order;
-    $other_params->{'select'} = [ 'me.id' ];
-    $other_params->{'as'}     = [ 'id' ];
-
-    $anzahl_buecher = $c->model('Schema::BuchListe')->count( $b_search_params, $other_params );
-    $c->log->debug(  get_output_string( $K, "Anzahl gefundene Buecher: ", $anzahl_buecher ) ) if $c->stash->{'debug_level'} >= 2;
-
-       my $page = to_int( $params->{'page'} ) ? to_int( $params->{'page'} ) : undef;
-       my $rows = undef;
-       $rows = ( $params->{'list_length'} || $c->stash->{'list_length'} || 20 ) if defined $page;
-
-       if ( $page ) {
-               $other_params->{'rows'} = $rows;
-               $other_params->{'page'} = $page;
-       }
-    #$other_params->{'rows'} = $c->stash->{'list_length'} || 20;
-    #$other_params->{'page'} = $params->{'page'} || $c->stash->{'page'} || 1;
-
-    my $book_ids = [];
-
-    for my $book ( $c->model('Schema::BuchListe')->search( $b_search_params, $other_params )->all() ) {
-        push @$book_ids, $book->get_column('id');
-    }
-
-    return ( wantarray ? ( $book_ids, 0 ) : $book_ids ) unless scalar( @$book_ids );
-
-    my $in = "IN ( " . join( ", ", @$book_ids ) . " )";
-
-    $b_search_params = { 'me.id' => \$in };
-
-    $other_params = {};
-    $other_params->{'join'}     = [ 'waehrung', 'verlag', 'ort', 'bindungsart' ];
-    $other_params->{'select'} = [
-        'me.id',
-        'me.title',
-        'me.title_original',
-        'me.untertitel',
-        'me.bindungsart_id',
-        'bindungsart.art_name',
-        'me.verlags_id',
-        'me.orts_id',
-        'me.isbn',
-        'me.buch_nr',
-        'me.ausgabejahr',
-        'me.druckjahr',
-        'me.seiten',
-        'me.kurzinhalt',
-        'me.preis',
-        'me.waehrungs_id',
-        'waehrung.waehrungs_kuerzel',
-        'waehrung.waehrungs_name',
-        'waehrung.umrechnung_in_euro',
-        'verlag.name_short',
-        'verlag.name_long',
-        'ort.name',
-        'ort.descr',
-        'ort.statisch',
-    ];
-    $other_params->{'as'} = [
-        'id',
-        'title',
-        'title_original',
-        'untertitel',
-        'bindungsart_id',
-        'bindungsart',
-        'verlags_id',
-        'orts_id',
-        'isbn',
-        'buch_nr',
-        'ausgabejahr',
-        'druckjahr',
-        'seiten',
-        'kurzinhalt',
-        'preis',
-        'waehrungs_id',
-        'waehrungs_kuerzel',
-        'waehrungs_name',
-        'umrechnung_in_euro',
-        'verlagsname_short',
-        'verlagsname_long',
-        'ortsname',
-        'ort_beschreibung',
-        'ort_ist_statisch',
-    ];
-    my $buchmap = {};
-    for my $book ( $c->model('Schema::Buecher')->search( $b_search_params, $other_params )->all() ) {
-        my $buch = {};
-        my $id                        = $book->id();
-        $buch->{'id'}                 = $id;
-        $buch->{'title'}              = $book->title();
-        $buch->{'title_original'}     = $book->title_original();
-        $buch->{'untertitel'}         = $book->untertitel();
-        $buch->{'bindungsart_id'}     = $book->bindungsart_id();
-        $buch->{'bindungsart'}        = $book->get_column('bindungsart');
-        $buch->{'verlags_id'}         = $book->verlags_id();
-        $buch->{'orts_id'}            = $book->orts_id();
-        $buch->{'isbn'}               = $book->isbn();
-        $buch->{'buch_nr'}            = $book->buch_nr();
-        $buch->{'ausgabejahr'}        = $book->ausgabejahr();
-        $buch->{'druckjahr'}          = $book->druckjahr();
-        $buch->{'seiten'}             = $book->seiten();
-        $buch->{'kurzinhalt'}         = $book->kurzinhalt();
-        $buch->{'preis'}              = $book->preis();
-        $buch->{'waehrungs_id'}       = $book->waehrungs_id();
-        $buch->{'waehrungs_kuerzel'}  = $book->get_column('waehrungs_kuerzel');
-        $buch->{'waehrungs_name'}     = $book->get_column('waehrungs_name');
-        $buch->{'umrechnung_in_euro'} = $book->get_column('umrechnung_in_euro');
-        $buch->{'verlagsname_short'}  = $book->get_column('verlagsname_short');
-        $buch->{'verlagsname_long'}   = $book->get_column('verlagsname_long');
-        $buch->{'ortsname'}           = $book->get_column('ortsname');
-        $buch->{'ort_beschreibung'}   = $book->get_column('ort_beschreibung');
-        $buch->{'ort_ist_statisch'}   = $book->get_column('ort_ist_statisch');
-        $buch->{'autoren'}            = [];
-        $buch->{'autor_ids'}          = [];
-        $buch->{'kategorien'}         = [];
-        $buch->{'kategorie_ids'}      = [];
-        $buch->{'serien'}             = [];
-        $buch->{'serien_ids'}         = [];
-        $buchmap->{$id} = $buch;
-    }
-
-    # Autoren zusammensammeln
-    my $a_search_params = {};
-    $a_search_params->{'buch_id'} = \$in;
-
-    $other_params = {};
-    $other_params->{'order_by'} = [ 'ord_num' ];
-    $other_params->{'join'}     = [ 'autor' ];
-    $other_params->{'select'} = [
-        'me.buch_id',
-        'autor.id',
-        'autor.titel',
-        'autor.vorname',
-        'autor.mittelname',
-        'autor.nachname',
-        'autor.name_suffix',
-    ];
-    $other_params->{'as'} = [
-        'buch_id',
-        'autor_id',
-        'titel',
-        'vorname',
-        'mittelname',
-        'nachname',
-        'name_suffix',
-    ];
-    for my $ref ( $c->model('Schema::Autor2buch')->search( $a_search_params, $other_params )->all() ) {
-        my $bid = $ref->get_column('buch_id');
-        my $aid = $ref->get_column('autor_id');
-        my @N;
-        if ( $short_author ) {
-            my $n;
-            if ( $ref->get_column('vorname') ) {
-                $n = substr( $ref->get_column('vorname'), 0, 1 );
-                $n .= ".";
-                push @N, $n;
-            }
-            if ( $ref->get_column('mittelname') ) {
-                $n = substr( $ref->get_column('mittelname'), 0, 1 );
-                $n .= ".";
-                push @N, $n;
-            }
-        }
-        else {
-            push @N, $ref->get_column('titel') if $ref->get_column('titel');
-            push @N, $ref->get_column('vorname') if $ref->get_column('vorname');
-            push @N, $ref->get_column('mittelname') if $ref->get_column('mittelname');
-        }
-        push @N, $ref->get_column('nachname');
-        push @N, $ref->get_column('name_suffix') if $ref->get_column('name_suffix');
-        my $autor = join( " ", @N );
-        push @{ $buchmap->{$bid}{'autoren'} },   $autor;
-        push @{ $buchmap->{$bid}{'autor_ids'} }, $aid;
-    }
-
-    # Kategorien zusammensammeln
-    delete $other_params->{'order_by'} if exists $other_params->{'order_by'};
-    $other_params->{'join'} = [ 'kategorie' ];
-    $other_params->{'select'} = [
-        'me.buch_id',
-        'kategorie.id',
-        'kategorie.kategorie_name',
-    ];
-    $other_params->{'as'} = [
-        'buch_id',
-        'kategorie_id',
-        'kategorie_name',
-    ];
-    for my $ref ( $c->model('Schema::Buch2kategorie')->search( $a_search_params, $other_params )->all() ) {
-        my $bid  = $ref->get_column('buch_id');
-        my $kid  = $ref->get_column('kategorie_id');
-        my $name = $ref->get_column('kategorie_name');
-        push @{ $buchmap->{$bid}{'kategorien'} },    $name;
-        push @{ $buchmap->{$bid}{'kategorie_ids'} }, $kid;
-    }
-
-    # Buchserien zusammensammeln
-    delete $other_params->{'order_by'} if exists $other_params->{'order_by'};
-    $other_params->{'join'} = [ 'serie' ];
-    $other_params->{'select'} = [
-        'me.buch_id',
-        'serie.id',
-        'serie.serien_name',
-    ];
-    $other_params->{'as'} = [
-        'buch_id',
-        'serien_id',
-        'serien_name',
-    ];
-    for my $ref ( $c->model('Schema::Buch2serie')->search( $a_search_params, $other_params )->all() ) {
-        my $bid  = $ref->get_column('buch_id');
-        my $sid  = $ref->get_column('serien_id');
-        my $name = $ref->get_column('serien_name');
-        push @{ $buchmap->{$bid}{'serien'} },     $name;
-        push @{ $buchmap->{$bid}{'serien_ids'} }, $sid;
-    }
-
-    # HashRef %$buchmap sortiert in ArrayRef $list ummappen
-
-    for my $id ( @$book_ids ) {
-        push @$list, $buchmap->{$id} if $buchmap->{$id};
-    }
-
-    return ( wantarray ? ( $list, $anzahl_buecher ) : $list );
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 get_booklist_sort_columns( )
-
-Gibt eine Hash-Ref mit allen verfügbaren Spaltennamen zurück, nach denen
-die Bücherliste sortiert werden kann.
-
-=cut
-
-sub get_booklist_sort_columns {
-
-    Readonly::Scalar my $valid_columns => {
-        'autoren'        => 'Autor/-en',
-        'title'          => 'Buchtitel',
-        'title_original' => 'Original Buchtitel',
-        'bindungsart'    => 'Bindungsart',
-        'verlag'         => 'Buchverlag',
-        'ort'            => 'Aufbewahrungsort',
-        'preis'          => 'Preis',
-        'waehrung'       => 'Währung des Buchpreises',
-        'ausgabejahr'    => 'Ausgabejahr',
-        'druckjahr'      => 'Druckjahr',
-        'seiten'         => 'Seitenzahl',
-        'kategorien'     => 'Buchketagorie(-n)',
-        'serien'         => 'Zyklus/Reihe',
-    };
-
-    return $valid_columns;
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 collect_sort_criteria( $c, [ $criteria ] )
-
-Sammelt aus der Sitzung die Sortierkriterien der Buchliste zusammen und gibt diese verwendbar
-für get_booklist() zurück.
-
-Die Sortierkriterien müssen in der Sitzung unter dem Schlüssel 'book_order_criteria'
-als Array-Ref abgelegt sein. Die Elemente der Array-Ref sind entweder Scalare mit den
-Spaltennamen oder Hashrefs der Form [ { 'autoren' => 'desc' }, { 'kategorien' => 'asc' }, ...].
-
-Es kann auch als weiterer Parameter eine Array-Ref mit den Sorierkriterien uebergeben werden.
-In diesem Fall wird der Sitzungsschluessel 'book_order_criteria' nicht beruecksichtigt.
-
-Folgende Spaltennamen dürfen verwendet werden:
-
-  - autoren
-  - title
-  - title_original
-  - bindungsart
-  - verlag
-  - ort
-  - preis
-  - waehrung
-  - ausgabejahr
-  - druckjahr
-  - seiten
-  - kategorien
-  - serien
-
-Falls in $c->session->{'book_order_criteria'} nichts liegt, wird folgendes
-als Voreinstellung verwendet:
-
-    $criteria = [
-        'autoren',
-        'title',
-    ];
-
-=cut
-
-sub collect_sort_criteria {
-
-    my $c = shift;
-    my $K = ( caller(0) )[3] . "(): ";
-
-    my $given_criteria = shift;
-
-    my $order = [];
-
-    my $valid_column = get_booklist_sort_columns();
-
-    my $used_column = {};
-
-    $given_criteria = undef unless ( $given_criteria and ref($given_criteria) and ref($given_criteria) eq 'ARRAY' );
-
-    my $criteria = ( $given_criteria or $c->session->{'book_order_criteria'} );
-    unless ( $criteria and ref($criteria) and ref($criteria) eq 'ARRAY' and scalar(@$criteria) ) {
-        $criteria = [
-            'autoren',
-            'title',
-        ];
-    }
-
-    my $col;
-    for my $crit ( @$criteria ) {
-        if ( ref($crit) and ref($crit) eq 'HASH' ) {
-            for my $key ( keys %$crit ) {
-                $col = lc($key);
-                if ( $valid_column->{$col} and not exists $used_column->{$col} ) {
-                    my $dir = $crit->{$key};
-                    $dir = ( $dir =~ /desc/i ) ? 'DESC' : 'ASC';
-                    $used_column->{$col} = 1;
-                    push @$order, ( $dir eq 'ASC' ? $col : \"`$col` DESC" );
-                }
-            }
-        }
-        else {
-            $col = lc($crit);
-            if ( $valid_column->{$col} and not exists $used_column->{$col} ) {
-                push @$order, $col;
-                $used_column->{$col} = 1;
-            }
-        }
-    }
-
-    $order = [ 'title' ] unless scalar( @$order );
-
-    return $order;
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 delete_book( $c, $book_id )
-
-Loescht das Buch mit der uebergebenen Buch-Id
-
-=cut
-
-sub delete_book {
-
-    my $c       = shift;
-    my $book_id = shift;
-    my $K       = ( caller(0) )[3] . "(): ";
-
-    $c->log->debug( $K . "aufgerufen fuer Buch-Id " . ( defined $book_id ? $book_id : '<undef>' ) . "." ) if $c->stash->{'debug_level'} > 2;
-
-    return undef unless $book_id and to_int($book_id);
-    $book_id = to_int($book_id);
-
-    my $schema =  $c->model('Schema')->{'schema'};
-    #$c->log->debug( get_output_string( $K . "Schema: ", $schema ) ) if $c->stash->{'debug_level'} > 4;
-    my $search_params = {
-        'buch_id' => $book_id,
-    };
-
-    my $coderef = sub {
-        $c->model('Schema::Autor2buch')->search( $search_params )->delete();
-        $c->model('Schema::Buch2kategorie')->search( $search_params )->delete();
-        $c->model('Schema::Buch2serie')->search( $search_params )->delete();
-        $c->model('Schema::Buecher')->search( { 'id' => $book_id } )->delete();
-    };
-
-    my $rs;
-    eval {
-        $rs = $schema->txn_do($coderef);
-    };
-
-    if ($@) {                             # Transaction failed
-        die "Rollback nicht erfolgreich!" if ($@ =~ /Rollback failed/i );     # Rollback failed
-        die $@;
-    }
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 save_book( $c, $book )
-
-  $book = {
-    'ausgabejahr' => '2004',
-    'autoren' => [
-      '11'
-    ],
-    'bindungsart_id' => 4,
-    'book_nr' => '',
-    'druckjahr' => '2006',
-    'isbn' => '3-492-70076-4',
-    'kategorien' => [
-      '2'
-    ],
-    'kurzinhalt' => 'bla bla bla',
-    'original_title' => '',
-    'orts_id' => '2',
-    'preis' => 14,
-    'seiten' => '640',
-    'serien' => [
-      '4'
-    ],
-    'title' => 'Die Zwerge',
-    'untertitel' => '',
-    'verlags_id' => '8',
-    'waehrungs_id' => '1'
-  };
-
-=cut
-
-sub save_book {
-
-    my $c    = shift;
-    my $book = shift;
-    my $K    = ( caller(0) )[3] . "(): ";
-
-    $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2;
-
-    my $storage = $c->stash->{'storage'};
-
-    my $tmp = $book->{'kurzinhalt'};
-    $tmp = '' unless defined $tmp;
-    $tmp =~ s/^\s+//;
-    $tmp =~ s/\s+$//;
-       $book->{'kurzinhalt'} = $tmp eq '' ? undef : $tmp;
-
-    my $save_func = sub {
-
-        my $storage = shift;
-        my $dbh     = shift;
-        my $buch    = shift;
-
-        my $sql = <<ENDE;
-INSERT INTO `buecher` (
-    `id`, `title`, `title_original`, `untertitel`, `verlags_id`, `orts_id`, `kurzinhalt`,
-    `bindungsart_id`, `isbn`, `buch_nr`, `ausgabejahr`, `druckjahr`, `seiten`, `preis`, `waehrungs_id` )
-  VALUES (
-    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
-  ON DUPLICATE KEY UPDATE
-    `id`             = LAST_INSERT_ID(`id`),
-    `title`          = ?,
-    `title_original` = ?,
-    `untertitel`     = ?,
-    `verlags_id`     = ?,
-    `orts_id`        = ?,
-    `kurzinhalt`     = ?,
-    `bindungsart_id` = ?,
-    `isbn`           = ?,
-    `buch_nr`        = ?,
-    `ausgabejahr`    = ?,
-    `druckjahr`      = ?,
-    `seiten`         = ?,
-    `preis`          = ?,
-    `waehrungs_id`   = ?
-ENDE
-
-        my @params = ();
-        push @params, $buch->{'id'};
-        push @params, $buch->{'title'};
-        push @params, $buch->{'original_title'};
-        push @params, $buch->{'untertitel'};
-        push @params, $buch->{'verlags_id'};
-        push @params, $buch->{'orts_id'};
-        push @params, $buch->{'kurzinhalt'};
-        push @params, $buch->{'bindungsart_id'};
-        push @params, $buch->{'isbn'};
-        push @params, $buch->{'book_nr'};
-        push @params, $buch->{'ausgabejahr'};
-        push @params, $buch->{'druckjahr'};
-        push @params, $buch->{'seiten'};
-        push @params, $buch->{'preis'};
-        push @params, $buch->{'waehrungs_id'};
-
-        push @params, $buch->{'title'};
-        push @params, $buch->{'original_title'};
-        push @params, $buch->{'untertitel'};
-        push @params, $buch->{'verlags_id'};
-        push @params, $buch->{'orts_id'};
-        push @params, $buch->{'kurzinhalt'};
-        push @params, $buch->{'bindungsart_id'};
-        push @params, $buch->{'isbn'};
-        push @params, $buch->{'book_nr'};
-        push @params, $buch->{'ausgabejahr'};
-        push @params, $buch->{'druckjahr'};
-        push @params, $buch->{'seiten'};
-        push @params, $buch->{'preis'};
-        push @params, $buch->{'waehrungs_id'};
-
-        if ( $storage->debug() ) {
-            my $text = $sql;
-            $text =~ s/\s+$//;
-            $text .= ": " . join( ", ", map { $dbh->quote($_) } @params ) . "\n";
-            warn $text;
-        }
-
-        my $sth = $dbh->prepare($sql);
-        $sth->execute( @params );
-
-    };
-
-    $storage->dbh_do( $save_func, $book );
-
-    my $book_id = $storage->last_insert_id();
-
-    return undef unless $book_id;
-
-    save_buch_autoren( $c, $book_id, $book->{'autoren'} );
-    save_buch_kategorien( $c, $book_id, $book->{'kategorien'} );
-    save_buch_serien( $c, $book_id, $book->{'serien'} );
-
-    return $book_id;
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 save_buch_autoren( $c, $book_id, @$autor_ids )
-
-=cut
-
-sub save_buch_autoren {
-
-    my $c         = shift;
-    my $book_id   = shift;
-    my $autor_ids = shift;
-
-    my $K    = ( caller(0) )[3] . "(): ";
-
-    my $storage = $c->stash->{'storage'};
-    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
-    my $dbh = $storage->dbh();
-    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
-
-    my $anzahl = 0;
-    $anzahl = scalar( @$autor_ids ) if $autor_ids and ref($autor_ids) and ref($autor_ids) eq 'ARRAY';
-
-    my $in = '';
-    $in = '(' . join( ", ", map { $dbh->quote($_) } @$autor_ids ) . ")" if $anzahl;
-
-    my $sql;
-    $sql = <<ENDE;
-DELETE FROM `autor2buch`
- WHERE `buch_id` = ?
-ENDE
-    $sql .= "   AND `autor_id` NOT IN " . $in . "\n" if $anzahl;
-
-    my $qparams = [];
-    push @$qparams, $book_id;
-
-    if ( $storage->debug() ) {
-        my $text = $sql;
-        $text =~ s/\s+$//;
-        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-        warn $text;
-    }
-
-    my $sth = $dbh->prepare($sql);
-    $sth->execute( @$qparams );
-
-    return 1 unless $anzahl;
-
-    my $i = 0;
-
-    $sql = <<ENDE;
-INSERT INTO `autor2buch` (
-    `buch_id`, `autor_id`, `ord_num`
-  ) VALUES (
-    ?, ?, ? )
-  ON DUPLICATE KEY UPDATE
-    `ord_num` = ?
-ENDE
-
-    $sth = $dbh->prepare($sql);
-
-    for my $autor_id ( @$autor_ids ) {
-
-        $qparams = [];
-        push @$qparams, $book_id;
-        push @$qparams, $autor_id;
-        push @$qparams, $i;
-        push @$qparams, $i;
-
-        if ( $storage->debug() ) {
-            my $text = $sql;
-            $text =~ s/\s+$//;
-            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-            warn $text;
-        }
-
-        $sth->execute( @$qparams );
-
-        $i++;
-    }
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 save_buch_serien( $c, $book_id, @$serien_ids )
-
-=cut
-
-sub save_buch_serien {
-
-    my $c          = shift;
-    my $book_id    = shift;
-    my $serien_ids = shift;
-
-    my $K    = ( caller(0) )[3] . "(): ";
-
-    my $storage = $c->stash->{'storage'};
-    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
-    my $dbh = $storage->dbh();
-    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
-
-    my $anzahl = 0;
-    $anzahl = scalar( @$serien_ids ) if $serien_ids and ref($serien_ids) and ref($serien_ids) eq 'ARRAY';
-
-    my $in = '';
-    $in = '(' . join( ", ", map { $dbh->quote($_) } @$serien_ids ) . ")" if $anzahl;
-
-    my $sql;
-    $sql = <<ENDE;
-DELETE FROM `buch2serie`
- WHERE `buch_id` = ?
-ENDE
-    $sql .= "   AND `serien_id` NOT IN " . $in . "\n" if $anzahl;
-
-    my $qparams = [];
-    push @$qparams, $book_id;
-
-    if ( $storage->debug() ) {
-        my $text = $sql;
-        $text =~ s/\s+$//;
-        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-        warn $text;
-    }
-
-    my $sth = $dbh->prepare($sql);
-    $sth->execute( @$qparams );
-
-    return 1 unless $anzahl;
-
-    my $i = 1;
-
-    $sql = <<ENDE;
-INSERT INTO `buch2serie` (
-    `buch_id`, `serien_id`, `ord_num`
-  ) VALUES (
-    ?, ?, ? )
-  ON DUPLICATE KEY UPDATE
-    `ord_num` = IFNULL( `ord_num`, ? )
-ENDE
-
-    $sth = $dbh->prepare($sql);
-
-    for my $serien_id ( @$serien_ids ) {
-
-        $qparams = [];
-        push @$qparams, $book_id;
-        push @$qparams, $serien_id;
-        push @$qparams, $i;
-        push @$qparams, $i;
-
-        if ( $storage->debug() ) {
-            my $text = $sql;
-            $text =~ s/\s+$//;
-            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-            warn $text;
-        }
-
-        $sth->execute( @$qparams );
-
-        $i++;
-    }
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head2 save_buch_kategorien( $c, $book_id, @$kategorie_ids )
-
-=cut
-
-sub save_buch_kategorien {
-
-    my $c             = shift;
-    my $book_id       = shift;
-    my $kategorie_ids = shift;
-
-    my $K    = ( caller(0) )[3] . "(): ";
-
-    my $storage = $c->stash->{'storage'};
-    # $c->log->debug( get_output_string( $K . "Storage: ", $storage ) ) if $c->stash->{'debug_level'} > 4;
-    my $dbh = $storage->dbh();
-    # $c->log->debug( get_output_string( $K . "DBH: ", $dbh ) ) if $c->stash->{'debug_level'} > 2;
-
-    my $anzahl = 0;
-    $anzahl = scalar( @$kategorie_ids ) if $kategorie_ids and ref($kategorie_ids) and ref($kategorie_ids) eq 'ARRAY';
-
-    my $in = '';
-    $in = '(' . join( ", ", map { $dbh->quote($_) } @$kategorie_ids ) . ")" if $anzahl;
-
-    my $sql;
-    $sql = <<ENDE;
-DELETE FROM `buch2kategorie`
- WHERE `buch_id` = ?
-ENDE
-    $sql .= "   AND `kategorie_id` NOT IN " . $in . "\n" if $anzahl;
-
-    my $qparams = [];
-    push @$qparams, $book_id;
-
-    if ( $storage->debug() ) {
-        my $text = $sql;
-        $text =~ s/\s+$//;
-        $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-        warn $text;
-    }
-
-    my $sth = $dbh->prepare($sql);
-    $sth->execute( @$qparams );
-
-    return 1 unless $anzahl;
-
-    $sql = <<ENDE;
-INSERT INTO `buch2kategorie` (
-    `buch_id`, `kategorie_id`
-  ) VALUES (
-    ?, ? )
-  ON DUPLICATE KEY UPDATE
-    `kategorie_id` = `kategorie_id`
-ENDE
-
-    $sth = $dbh->prepare($sql);
-
-    for my $kategorie_id ( @$kategorie_ids ) {
-
-        $qparams = [];
-        push @$qparams, $book_id;
-        push @$qparams, $kategorie_id;
-
-        if ( $storage->debug() ) {
-            my $text = $sql;
-            $text =~ s/\s+$//;
-            $text .= ": " . join( ", ", map { $dbh->quote($_) } @$qparams ) . "\n";
-            warn $text;
-        }
-
-        $sth->execute( @$qparams );
-
-    }
-
-}
-
-#-----------------------------------------------------------------------------------
-
-=head1 AUTHOR
-
-Frank Brehm
-
-=head1 LICENSE
-
-This library is free software, you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-1;
-
-__END__
-
-# vim: noai : ts=4 fenc=utf-8 filetype=perl expandtab :