Browse Source

Bug 22569: Add a 'Transfers to send' report

This patch adds a 'Transfers to send' report to the circulation page
which displays items which have been triggered for transfer but not
marked as sent.

Test plan
1) Setup a rotation plan and add some items to it as per the
   manual
2) Run the stockrotation cronjob with the --execute flag
3) Check that the expected items appear in the new 'Transfers to send'
   page.
4) Confirm that items marked with 'StockRotationAdvance' provide the
   option to mark the item as 'In demand' (Which will cancel the
   transfer and mark the item as in demand such that it will wait at the
   current branch for an additional stage period before being
   automatically picke for transfer again)
5) Setup a rotating collection
6) Trigger a collection transfer for the above collection
7) Check that the expected items appear in the new 'Transfers to send'
   page'.

Signed-off-by: Kathleen Milne <kathleen.milne@cne-siar.gov.uk>

Bug 22569: (QA follow-up) Rename script to snake_case

As requested, we simply rename the script, and references to it, to use
snake_case to make it clearer.

Bug 22569: (QA follow-up) Rename branchesloop to libraries

Bug 22569: (QA follow-up) Fix indentation in template

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
master
6 changed files with 256 additions and 8 deletions
  1. +28
    -0
      Koha/Library.pm
  2. +43
    -0
      Koha/StockRotationItem.pm
  3. +3
    -8
      Koha/Util/StockRotation.pm
  4. +64
    -0
      circ/transfers_to_send.pl
  5. +3
    -0
      koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt
  6. +115
    -0
      koha-tmpl/intranet-tmpl/prog/en/modules/circ/transfers_to_send.tt

+ 28
- 0
Koha/Library.pm View File

@@ -51,6 +51,34 @@ sub stockrotationstages {
return Koha::StockRotationStages->_new_from_dbic( $rs );
}

=head3 outgoing_transfers

my $outgoing_transfers = Koha::Library->outgoing_transfers;

Returns the outgoing item transfers associated with this Library.

=cut

sub outgoing_transfers {
my ( $self ) = @_;
my $rs = $self->_result->branchtransfers_frombranches;
return Koha::Item::Transfers->_new_from_dbic( $rs );
}

=head3 inbound_transfers

my $inbound_transfers = Koha::Library->inbound_transfers;

Returns the inbound item transfers associated with this Library.

=cut

sub inbound_transfers {
my ( $self ) = @_;
my $rs = $self->_result->branchtransfers_tobranches;
return Koha::Item::Transfers->_new_from_dbic( $rs );
}

=head3 get_effective_marcorgcode

my $marcorgcode = Koha::Libraries->find( $library_id )->get_effective_marcorgcode();


+ 43
- 0
Koha/StockRotationItem.pm View File

@@ -277,6 +277,49 @@ sub advance {
return $transfer;
}

=head3 toggle_indemand

$sritem->toggle_indemand;

Toggle this items in_demand status.

If the item is in the process of being advanced to the next stage then we cancel
the transfer, revert the advancement and reset the 'StockrotationAdvance' counter,
as though 'in_demand' had been set prior to the call to advance, by updating the
in progress transfer.

=cut

sub toggle_indemand {
my ( $self ) = @_;

# Toggle the item's indemand flag
my $new_indemand = ($self->indemand == 1) ? 0 : 1;

# Cancel 'StockrotationAdvance' transfer if one is in progress
if ($new_indemand) {
my $item = $self->itemnumber;
my $transfer = $item->get_transfer;
if ($transfer && $transfer->reason eq 'StockrotationAdvance') {
my $stage = $self->stage;
my $new_stage;
if ( $stage->rota->cyclical && !$stage->first_sibling ) { # First stage
$new_stage = $stage->last_sibling;
} else {
$new_stage = $stage->previous_sibling;
}
$self->stage_id($new_stage->stage_id)->store; # Revert stage change
$item->homebranch($new_stage->branchcode_id)->store; # Revert update homebranch
$new_indemand = 0; # Reset indemand
$transfer->tobranch($new_stage->branchcode_id); # Reset StockrotationAdvance
$transfer->datearrived(dt_from_string); # Reset StockrotationAdvance
$transfer->store;
}
}

$self->indemand($new_indemand)->store;
}

=head3 investigate

my $report = $item->investigate;


+ 3
- 8
Koha/Util/StockRotation.pm View File

@@ -97,21 +97,16 @@ sub get_stages {

sub toggle_indemand {

my ($item_id, $stage_id) = @_;
my ($item_id) = @_;

# Get the item object
my $item = Koha::StockRotationItems->find(
my $sr_item = Koha::StockRotationItems->find(
{
itemnumber_id => $item_id,
stage_id => $stage_id
}
);

# Toggle the item's indemand flag
my $new_indemand = ($item->indemand == 1) ? 0 : 1;

$item->indemand($new_indemand)->store;

$sr_item->toggle_indemand;
}

=head2 move_to_next_stage


+ 64
- 0
circ/transfers_to_send.pl View File

@@ -0,0 +1,64 @@
#!/usr/bin/perl

# Copyright 2019 PTFS-Europe Ltd.
#
# 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::DateUtils;

my $input = CGI->new;
my $itemnumber = $input->param('itemnumber');

my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user(
{
template_name => "circ/transfers_to_send.tt",
query => $input,
type => "intranet",
flagsrequired => { circulate => "circulate_remaining_permissions" },
debug => 1,
}
);

# set the userenv branch
my $branchcode = C4::Context->userenv->{'branch'};

# transfers requested but not yet sent
my @transfers = Koha::Libraries->search(
{
'branchtransfers_tobranches.frombranch' => $branchcode,
'branchtransfers_tobranches.daterequested' => { '!=' => undef },
'branchtransfers_tobranches.datesent' => undef,
'branchtransfers_tobranches.datearrived' => undef,
'branchtransfers_tobranches.datecancelled' => undef,
},
{
prefetch => 'branchtransfers_tobranches',
order_by => 'branchtransfers_tobranches.tobranch'
}
);

$template->param(
libraries => \@transfers,
show_date => dt_from_string
);

output_html_with_http_headers $input, $cookie, $template->output;

+ 3
- 0
koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt View File

@@ -97,6 +97,9 @@
<a class="circ-button" href="/cgi-bin/koha/circ/branchtransfers.pl"><i class="fa fa-exchange"></i> Transfer</a>
</li>
[% END %]
<li>
<a class="circ-button" href="/cgi-bin/koha/circ/transfers_to_send.pl"><i class="fa fa-sign-out"></i> Transfers to send</a>
</li>
<li>
<a class="circ-button" href="/cgi-bin/koha/circ/transferstoreceive.pl"><i class="fa fa-sign-in"></i> Transfers to receive</a>
</li>


+ 115
- 0
koha-tmpl/intranet-tmpl/prog/en/modules/circ/transfers_to_send.tt View File

@@ -0,0 +1,115 @@
[% USE raw %]
[% USE Asset %]
[% USE Koha %]
[% USE KohaDates %]
[% USE Branches %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Circulation &rsaquo; Transfers to send</title>
[% INCLUDE 'doc-head-close.inc' %]
</head>

<body id="circ_transferstosend" class="circ">
[% INCLUDE 'header.inc' %]
[% INCLUDE 'circ-search.inc' %]

<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> &rsaquo; Transfers to send</div>

<div class="main container-fluid">
<div class="row">
<div class="col-sm-12">
<main>
<div class="row">

[% IF Koha.Preference('CircSidebar') %]
<div class="col-sm-10 col-sm-push-2">
[% ELSE %]
<div class="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
[% END %]

<h1>Transfers requested of your library as of [% show_date | $KohaDates %]</h1>

[% IF ( libraries ) %]
<p>Your library is the origin for the following transfer(s)</p>
<div id="resultlist">
[% FOREACH library IN libraries %]
[% IF ( library.branchcode ) %]
<table style="width: 100%" id="transferst[% library.branchcode | html %]">
<caption>Sending to [% library.branchname | html %]</caption>
<thead>
<tr>
<th class="title-string">Date of request</th>
<th class="anti-the">Title</th>
<th>Reason</th>
<th>On loan</th>
<th>Home library</th>
<th>Call no.</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
[% FOREACH transfer IN library.inbound_transfers %]
[% UNLESS transfer.datesent %]
<tr>
<td><p><span title="[% transfer.daterequested | html %]">[% transfer.daterequested | $KohaDates %]</span></p></td>
<td>
[% INCLUDE 'biblio-title.inc' biblio = transfer.item.biblio link = 1 %][% IF ( transfer.item.biblio.author ) %] by [% transfer.item.biblio.author | html %][% END %]
[% IF ( transfer.item.effective_itemtype ) %] (<b>[% transfer.item.effective_itemtype | html %]</b>)[% END %]
<br />Barcode: [% transfer.item.barcode | html %]
</td>
<td><p>[% transfer.reason | html %]</p></td>
<td>[% IF transfer.item.onloan %]Due [% transfer.item.onloan | $KohaDates %][% ELSE %]On shelf[% END %]</td>
<td>[% Branches.GetName( transfer.item.homebranch ) | html %]</td>
<td>[% transfer.item.itemcallnumber | html %]</td>
<td class="actions">
[% IF transfer.reason == 'StockrotationAdvance' %]
<a href="/cgi-bin/koha/catalogue/stockrotation.pl?op=toggle_in_demand&stage_id=4&item_id=[% transfer.itemnumber | uri %]&biblionumber=[% transfer.item.biblionumber | uri %]" class="btn btn-default btn-xs"><i class="fa fa-fire"></i> Mark "In demand"</a>
[% END %]
</td>
</tr>
[% END %]
[% END %]
</tbody>
</table>
[% END %]
[% END %]
</div>
[% ELSE %]
<p>No transfers to send</p>
[% END %]

</div> <!-- /.col-sm-10.col-sm-push-2 OR /.col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2-->

[% IF Koha.Preference('CircSidebar') %]
<div class="col-sm-2 col-sm-pull-10">
<aside>
[% INCLUDE 'circ-nav.inc' %]
</aside>
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
[% END %]

</div> <!-- /.row -->
</main>
</div> <!-- /.col-sm-12 -->
</div> <!-- /.row -->

[% MACRO jsinclude BLOCK %]
[% INCLUDE 'datatables.inc' %]
<script>
$(document).ready(function() {
[% FOREACH library IN libraries %]
$("#transferst[% library.branchcode | html %]").dataTable($.extend(true, {}, dataTablesDefaults, {
"aoColumnDefs": [
{ "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
{ "sType": "anti-the", "aTargets" : [ "anti-the" ] },
{ "sType": "title-string", "aTargets" : [ "title-string" ] }
],
"sDom": 't',
"bPaginate": false
}));
[% END %]
});
</script>
[% END %]

[% INCLUDE 'intranet-bottom.inc' %]

Loading…
Cancel
Save