Bug 13881: Add desk management
authorNicolas Legrand <nicolas.legrand@bulac.fr>
Wed, 2 Oct 2019 12:09:21 +0000 (14:09 +0200)
committerMartin Renvoize <martin.renvoize@ptfs-europe.com>
Wed, 25 Mar 2020 09:19:15 +0000 (09:19 +0000)
Add a desk and linked it to a library (branch). That's it. In the
future it'll have super features like being able to link waiting
reserve to a specific desk.

Test plan:

1. go to the administration page and notice there isn't any mention of
desk whatsoever
2. apply patches
3. ./installer/data/mysql/updatedatabase.pl
4. prove t/db_dependent/Koha/Desks.t
5. you now have desks links in admin-home and admin-menu
6. click the link
7. add a desk
8. add another one
9. delete one
10. you should have a fair list of all current desks defined
11. Done

Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr>
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Koha/Desk.pm [new file with mode: 0644]
Koha/Desks.pm [new file with mode: 0644]
admin/desks.pl [new file with mode: 0755]
koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc
koha-tmpl/intranet-tmpl/prog/en/includes/desks-admin-search.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt
koha-tmpl/intranet-tmpl/prog/en/modules/admin/desks.tt [new file with mode: 0644]
t/db_dependent/Koha/Desks.t [new file with mode: 0644]

diff --git a/Koha/Desk.pm b/Koha/Desk.pm
new file mode 100644 (file)
index 0000000..cd4379d
--- /dev/null
@@ -0,0 +1,45 @@
+package Koha::Desk;
+
+# Copyright (C) 2020 BULAC
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Carp;
+
+use Koha::Database;
+
+use base qw(Koha::Object);
+
+=head1 NAME
+
+Koha::Desk - Koha Desk Object class
+
+=head1 API
+
+=head2 Class Methods
+
+=cut
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'Desk';
+}
+
+1;
diff --git a/Koha/Desks.pm b/Koha/Desks.pm
new file mode 100644 (file)
index 0000000..a8b452c
--- /dev/null
@@ -0,0 +1,56 @@
+package Koha::Desks;
+
+# Copyright (C) 2020 BULAC
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+
+use Modern::Perl;
+
+use Carp;
+
+use Koha::Database;
+
+use Koha::Desk;
+
+use base qw(Koha::Objects);
+
+=head1 NAME
+
+Koha::Desks - Koha Desk Object set class
+
+=head1 API
+
+=head2 Class Methods
+
+=cut
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'Desk';
+}
+
+=head3 object_class
+
+=cut
+
+sub object_class {
+    return 'Koha::Desk';
+}
+
+1;
diff --git a/admin/desks.pl b/admin/desks.pl
new file mode 100755 (executable)
index 0000000..fb654e9
--- /dev/null
@@ -0,0 +1,114 @@
+#! /usr/bin/perl
+
+# Copyright (C) 2020 BULAC
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+
+use Modern::Perl;
+use CGI qw ( -utf8 );
+use C4::Context;
+use C4::Auth;
+use C4::Output;
+
+use Koha::Desks;
+
+my $input       = new CGI;
+my $searchfield = $input->param('desk_name') // q||;
+my $desk_id      = $input->param('desk_id') || '';
+my $op          = $input->param('op') || 'list';
+my @messages;
+
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
+    {   template_name   => "admin/desks.tt",
+        query           => $input,
+        type            => "intranet",
+        authnotrequired => 0,
+        flagsrequired   => { parameters => 'manage_desks' },
+        debug           => 1,
+    }
+);
+
+my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
+
+if ( $op eq 'add_form' ) {
+    my $desk;
+    if ($desk_id) {
+        $desk = Koha::Desks->find($desk_id);
+    }
+
+    $template->param( desk => $desk, );
+} elsif ( $op eq 'add_validate' ) {
+    my $desk_id       = $input->param('desk_id');
+    my $desk_name    = $input->param('desk_name');
+    my $branchcode   = $input->param('branchcode');
+
+    if (Koha::Desks->find($desk_id)) {
+        my $desk = Koha::Desks->find($desk_id);
+        $desk->desk_name($desk_name);
+        $desk->branchcode($branchcode);
+        eval { $desk->store; };
+        if ($@) {
+            push @messages, { type => 'error', code => 'error_on_update' };
+        } else {
+            push @messages, { type => 'message', code => 'success_on_update' };
+        }
+    } else {
+        my $desk = Koha::Desk->new(
+            {
+                desk_id       => $desk_id,
+                desk_name    => $desk_name,
+                branchcode   => $branchcode,
+            }
+        );
+        eval { $desk->store; };
+        if ($@) {
+            push @messages, { type => 'error', code => 'error_on_insert' };
+        } else {
+            push @messages, { type => 'message', code => 'success_on_insert' };
+        }
+    }
+    $searchfield = q||;
+    $op          = 'list';
+} elsif ( $op eq 'delete_confirm' ) {
+    my $desk = Koha::Desks->find($desk_id);
+    $template->param( desk => $desk, );
+} elsif ( $op eq 'delete_confirmed' ) {
+    my $desk = Koha::Desks->find($desk_id);
+    my $deleted = eval { $desk->delete; };
+
+    if ( $@ or not $deleted ) {
+        push @messages, { type => 'error', code => 'error_on_delete' };
+    } else {
+        push @messages, { type => 'message', code => 'success_on_delete' };
+    }
+    $op = 'list';
+}
+
+if ( $op eq 'list' || ! $op) {
+    my $desks = Koha::Desks->search( { desk_name => { -like => "%$searchfield%" } } );
+    $template->param( desks => $desks, );
+}
+
+$template->param(
+    desk_id      => $desk_id,
+    searchfield => $searchfield,
+    messages    => \@messages,
+    op          => $op,
+    branches    => $branches,
+);
+
+output_html_with_http_headers $input, $cookie, $template->output;
index cb98dfe..fd5d595 100644 (file)
@@ -16,6 +16,7 @@
             [% IF ( CAN_user_parameters_manage_libraries ) %]
                 <li><a href="/cgi-bin/koha/admin/branches.pl">Libraries</a></li>
                 <li><a href="/cgi-bin/koha/admin/library_groups.pl">Library groups</a></li>
+                <li><a href="/cgi-bin/koha/admin/desks.pl">Desks</a></li>
             [% END %]
             [% IF ( CAN_user_parameters_manage_itemtypes ) %]
                 <li><a href="/cgi-bin/koha/admin/itemtypes.pl">Item types</a></li>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/desks-admin-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/desks-admin-search.inc
new file mode 100644 (file)
index 0000000..cde4c70
--- /dev/null
@@ -0,0 +1,31 @@
+[% USE Koha %]
+<div class="gradient">
+<h1 id="logo"><a href="/cgi-bin/koha/mainpage.pl">[% LibraryName|html %]</a></h1><!-- Begin Desks Resident Search Box -->
+<div id="header_search">
+        <div id="desk_search" class="residentsearch">
+    <p class="tip">Desk search:</p>
+        <form action="[% script_name|html %]" method="post">
+        <input class="head-searchbox" type="text" name="desk_name" value="[% searchfield|html %]" size="40" />
+                <input type="submit" name="submit" value="OK" class="submit" />
+        </form>
+        </div>
+
+    [% INCLUDE 'patron-search-box.inc' %]
+
+        [% IF ( CAN_user_catalogue ) %]
+    <div id="catalog_search" class="residentsearch">
+        <p class="tip">Enter search keywords:</p>
+                <form action="/cgi-bin/koha/catalogue/search.pl"  method="get" id="cat-search-block">
+             [% IF ( Koha.Preference('IntranetCatalogSearchPulldown') ) %][% INCLUDE 'search_indexes.inc' %][% END %]
+             <input type="text" name="q" id="search-form" size="40" value="" title="Enter the terms you wish to search for." class="head-searchbox form-text" />
+                                <input type="submit" value="Submit"  class="submit" />
+                </form>
+        </div>[% END %]
+                        <ul>
+            <li><a class="keep_text" href="#desk_search">Search desks</a></li>
+            [% IF ( CAN_user_circulate_circulate_remaining_permissions ) %]<li><a class="keep_text" href="#circ_search">Check out</a></li>[% END %]
+            [% IF ( CAN_user_catalogue ) %]<li><a class="keep_text" href="#catalog_search">Search the catalog</a></li>[% END %]
+                        </ul>
+</div>
+</div>
+<!-- End Desks Resident Search Box -->
index 8752229..e232516 100644 (file)
@@ -63,6 +63,8 @@
                         <dd>Define libraries.</dd>
                         <dt><a href="/cgi-bin/koha/admin/library_groups.pl">Library groups</a></dt>
                         <dd>Define hierarchical library groups.</dd>
+                        <dt><a href="/cgi-bin/koha/admin/desks.pl">Desks</a></dt>
+                        <dd>Define desks.</dd>
                     [% END %]
                     [% IF ( CAN_user_parameters_manage_itemtypes ) %]
                         <dt><a href="/cgi-bin/koha/admin/itemtypes.pl">Item types</a></dt>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/desks.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/desks.tt
new file mode 100644 (file)
index 0000000..6d35621
--- /dev/null
@@ -0,0 +1,190 @@
+[% USE raw %]
+[% USE Branches %]
+[% USE Asset %]
+[% SET footerjs = 1 %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Administration &rsaquo; [% IF op =='add_form' %]Desks &rsaquo; [% IF desk.desk_id %] Modify desk[% ELSE %] New desk[% END %][% ELSE %][% IF op == 'delete_confirm' %]Desks &rsaquo; Confirm deletion of desk[% ELSE %] Desks[% END %][% END %]</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="admin_desks" class="admin">
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'desks-admin-search.inc' %]
+
+<div id="breadcrumbs">
+    <a href="/cgi-bin/koha/mainpage.pl">Home</a>
+    &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
+    &rsaquo; <a href="/cgi-bin/koha/admin/desks.pl">Desks</a>
+    [% IF op == 'add_form' %]
+    &rsaquo; [% IF desk.desk_id %]Modify[% ELSE %]New[% END %] Desk
+    [% ELSIF op == 'delete_confirm' %]
+    &rsaquo; Confirm deletion of desk
+    [% END %]
+</div>
+
+<div class="main container-fluid">
+    <div class="row">
+        <div class="col-sm-10 col-sm-push-2">
+            <main>
+
+[% FOR m IN messages %]
+    <div class="dialog [% m.type | html %]">
+        [% SWITCH m.code %]
+        [% CASE 'error_on_update' %]
+            An error occurred when updating this desk. Perhaps it already exists.
+        [% CASE 'error_on_insert' %]
+            An error occurred when adding this desk. The desk id might already exist.
+        [% CASE 'error_on_delete' %]
+            An error occurred when deleting this desk. Check the logs.
+        [% CASE 'success_on_update' %]
+            Desk updated successfully.
+        [% CASE 'success_on_insert' %]
+            Desk added successfully.
+        [% CASE 'success_on_delete' %]
+            Desk deleted successfully.
+        [% CASE 'already_exists' %]
+            This desk already exists.
+        [% CASE %]
+            [% m.code | html %]
+        [% END %]
+    </div>
+[% END %]
+
+[% IF op == 'add_form' %]
+    [% IF desk %]
+        <h1>Modify a desk</h1>
+    [% ELSE %]
+        <h1>New desk</h1>
+    [% END %]
+
+    <form action="/cgi-bin/koha/admin/desks.pl" name="Aform" method="post" class="validated">
+        <input type="hidden" name="op" value="add_validate" />
+        <input type="hidden" name="desk_id" value="[% desk.desk_id | html %]" />
+
+        <fieldset class="rows">
+            <ol>
+                [% IF desk %]
+                    <li><span class="label">Desk ID: </span>[% desk.desk_id | html %]</li>
+                [% END %]
+                <li>
+                    <label for="desk_name" class="required">Desk: </label>
+                    <input type="text" name="desk_name" id="desk_name" size="80" maxlength="100" value="[% desk.desk_name | html %]" required="required" class="required" /> <span class="required">Required</span>
+                </li>
+                <li>
+                    <label for="branchcode" class="required">Library: </label>
+                    <select id="branchcode" name="branchcode" required="required">
+                      <option value=""></option>
+                      [% FOREACH branch IN branches %]
+                        [% IF (Branches.GetLoggedInBranchcode == branch.branchcode) %]
+                        <option value="[% branch.branchcode|html %]" selected="selected">[% branch.branchname|html %]</option>
+                        [% ELSE %]
+                        <option value="[% branch.branchcode|html %]">[% branch.branchname|html %]</option>
+                        [% END %]
+                      [% END %]
+                     </select>
+                </li>
+
+            </ol>
+        </fieldset>
+
+        <fieldset class="action">
+            <input type="submit" value="Submit" />
+            <a class="cancel" href="/cgi-bin/koha/admin/desks.pl">Cancel</a>
+        </fieldset>
+    </form>
+[% END %]
+
+[% IF op == 'delete_confirm' %]
+    <div class="dialog alert">
+        <h3>Delete desk "[% desk.desk_name | html %]?"</h3>
+        <table>
+            <tr><th>Desk id</th>
+                <td>[% desk.desk_id | html %]</td>
+            </tr>
+            <tr><th>Desk</th>
+                <td>[% desk.desk_name | html %]</td>
+            </tr>
+            <tr><th>Branchcode</th>
+                <td>[% desk.branchcode | html %]</td>
+            </tr>
+        </table>
+        <form action="/cgi-bin/koha/admin/desks.pl" method="post">
+            <input type="hidden" name="op" value="delete_confirmed" />
+            <input type="hidden" name="desk_id" value="[% desk.desk_id | html %]" />
+            <button type="submit" class="approve"><i class="fa fa-fw fa-check"></i> Yes, delete</button>
+        </form>
+        <form action="/cgi-bin/koha/admin/desks.pl" method="get">
+            <button type="submit" class="deny"><i class="fa fa-fw fa-remove"></i> No, do not delete</button>
+        </form>
+    </div>
+[% END %]
+
+[% IF op == 'list' %]
+
+    <div id="toolbar" class="btn-toolbar">
+        <a class="btn btn-default" id="newdesk" href="/cgi-bin/koha/admin/desks.pl?op=add_form"><i class="fa fa-plus"></i> New desk</a>
+    </div>
+
+    <h2>Desks</h2>
+    [% IF searchfield %]
+        Searching: [% searchfield | html %]
+    [% END %]
+
+    [% IF desks.count %]
+        <table id="table_desks">
+            <thead>
+                <tr>
+                    <th>Desk ID</th>
+                    <th>Desk</th>
+                    <th>Library</th>
+                    <th>Action</th>
+                </tr>
+            </thead>
+            <tbody>
+                [% FOREACH desk IN desks %]
+                <tr>
+                    <td>[% desk.desk_id | html %]</td>
+                    <td>[% desk.desk_name | html %]</td>
+                    <td>[% desk.branchcode | html %]</td>
+                    <td class="actions">
+                        <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/desks.pl?op=add_form&amp;desk_id=[% desk.desk_id | html %]"><i class="fa fa-pencil"></i> Edit</a>
+                        <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/desks.pl?op=delete_confirm&amp;desk_id=[% desk.desk_id | html %]"><i class="fa fa-trash"></i> Delete</a>
+                    </td>
+                </tr>
+                [% END %]
+            </tbody>
+        </table>
+    [% ELSE %]
+        <div class="dialog message">
+            There are no desks defined. <a href="/cgi-bin/koha/admin/desks.pl?op=add_form">Create a new desk</a>.
+        </div>
+    [% END %]
+[% END %]
+
+            </main>
+        </div> <!-- /.col-sm-10.col-sm-push-2 -->
+
+        <div class="col-sm-2 col-sm-pull-10">
+            <aside>
+                [% INCLUDE 'admin-menu.inc' %]
+            </aside>
+        </div> <!-- /.col-sm-2.col-sm-pull-10 -->
+     </div> <!-- /.row -->
+
+[% MACRO jsinclude BLOCK %]
+    [% Asset.js("js/admin-menu.js") | $raw %]
+    [% INCLUDE 'datatables.inc' %]
+    <script>
+        $(document).ready(function() {
+            $("#table_desks").dataTable($.extend(true, {}, dataTablesDefaults, {
+                "aoColumnDefs": [
+                    { "aTargets": [ -1, -2 ], "bSortable": false, "bSearchable": false },
+                ],
+                "aaSorting": [[ 1, "asc" ]],
+                "iDisplayLength": 10,
+                "sPaginationType": "full_numbers"
+            }));
+        });
+    </script>
+[% END %]
+[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/t/db_dependent/Koha/Desks.t b/t/db_dependent/Koha/Desks.t
new file mode 100644 (file)
index 0000000..8981445
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+
+# Copyright 2015 Koha Development team
+# Copyright 2020 BULAC
+#
+# This file is part of Koha
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Test::More tests => 4;
+
+use Koha::Desk;
+use Koha::Desks;
+use Koha::Database;
+use Koha::Libraries;
+
+use t::lib::TestBuilder;
+
+my $schema = Koha::Database->new->schema;
+$schema->storage->txn_begin;
+
+# Add CPL if missing.
+if (not defined Koha::Libraries->find('CPL')) {
+    Koha::Library->new({ branchcode => 'CPL', branchname => 'Centerville' })->store;
+}
+
+my $builder = t::lib::TestBuilder->new;
+my $nb_of_desks = Koha::Desks->search->count;
+my $new_desk_1 = Koha::Desk->new({
+    desk_name  => 'my_desk_name_for_test_1',
+    branchcode => 'CPL',
+})->store;
+my $new_desk_2 = Koha::Desk->new({
+    desk_name  => 'my_desk_name_for_test_2',
+    branchcode => 'CPL',
+})->store;
+
+like( $new_desk_1->desk_id, qr|^\d+$|, 'Adding a new desk should have set the desk_id');
+is( Koha::Desks->search->count, $nb_of_desks + 2, 'The 2 desks should have been added' );
+
+my $retrieved_desk_1 = Koha::Desks->find( $new_desk_1->desk_id );
+is( $retrieved_desk_1->desk_name, $new_desk_1->desk_name, 'Find a desk by id should return the correct desk' );
+
+$retrieved_desk_1->delete;
+is( Koha::Desks->search->count, $nb_of_desks + 1, 'Delete should have deleted the desk' );
+
+$schema->storage->txn_rollback;