Bugzilla – Attachment 63073 Details for
Bug 11897
Stock Rotation for Koha
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11897: Interface for rotas from Tools menu
Bug-11897-Interface-for-rotas-from-Tools-menu.patch (text/plain), 42.55 KB, created by
Alex Sassmannshausen
on 2017-05-04 09:39:15 UTC
(
hide
)
Description:
Bug 11897: Interface for rotas from Tools menu
Filename:
MIME Type:
Creator:
Alex Sassmannshausen
Created:
2017-05-04 09:39:15 UTC
Size:
42.55 KB
patch
obsolete
>From 9b26d00b1f9dbcffc0a4a0fe32339dd1a0d99537 Mon Sep 17 00:00:00 2001 >From: Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >Date: Wed, 14 Dec 2016 10:14:38 +0000 >Subject: [PATCH] Bug 11897: Interface for rotas from Tools menu > >* tools/stockrotation.pl: New file >* koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt: New file >* koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc: >--- > .../prog/en/includes/stockrotation-toolbar.inc | 13 + > .../prog/en/modules/tools/stockrotation.tt | 482 +++++++++++++++++++ > tools/stockrotation.pl | 519 +++++++++++++++++++++ > 3 files changed, 1014 insertions(+) > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt > create mode 100755 tools/stockrotation.pl > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc >new file mode 100644 >index 0000000000..5bc4a8b295 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/stockrotation-toolbar.inc >@@ -0,0 +1,13 @@ >+[% USE Koha %] >+<div id="toolbar" class="btn-toolbar"> >+ [% IF no_op_set %] >+ <a id="addrota" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_rota"><i class="fa fa-plus"></i> New rota</a> >+ [% END %] >+ [% IF op == 'manage_stages' %] >+ <a id="addstage" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_stage&rota_id=[% rota_id %]"><i class="fa fa-plus"></i> New stage</a> >+ [% END %] >+ [% IF op == 'manage_items' %] >+ <a id="addrota" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_rota"><i class="fa fa-plus"></i> New rota</a> >+ <a id="editrota" class="btn btn-small" href="/cgi-bin/koha/tools/stockrotation.pl?op=create_edit_rota&rota_id=[% rota_id %]"><i class="fa fa-pencil"></i> Edit rota</a> >+ [% END %] >+</div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt >new file mode 100644 >index 0000000000..acf9b89bbf >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/stockrotation.tt >@@ -0,0 +1,482 @@ >+[% USE Koha %] >+[% USE Branches %] >+[% USE KohaDates %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Stock rotation</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables.css" /> >+[% INCLUDE 'datatables.inc' %] >+<script type="text/javascript" src="[% interface %]/[% theme %]/js/pages/stockrotation.js"></script> >+<script type="text/javascript"> >+//<![CDATA[ >+ $(document).ready(function() { >+ $('#sr_manage_items').dataTable($.extend(true, {}, dataTablesDefaults, { >+ "autoWidth": false, >+ "aoColumnDefs": [ >+ { "bSortable": false, "bSearchable": false, 'aTargets': [ 'NoSort' ] }, >+ { "bSortable": true, "bSearchable": false, 'aTargets': [ 'NoSearch' ] } >+ ], >+ "sPaginationType": "four_button" >+ })); >+ }); >+//]]> >+</script> >+</head> >+ >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'patron-search.inc' %] >+ >+<div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> >+ › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> >+ >+[% IF no_op_set %] >+ › Stock rotation >+[% ELSE %] >+ › <a href="/cgi-bin/koha/tools/stockrotation.pl">Stock rotation</a> >+[% END %] >+ >+[% IF (op == 'create_edit_rota' && rota.rota_id) %] >+ › Edit rota >+[% ELSIF (op == 'create_edit_rota' && !rota.rota_id) %] >+ › Create rota >+[% ELSIF (op == 'manage_stages') %] >+ › Manage stages >+[% ELSIF (op == 'create_edit_stage' && stage.id) %] >+ <a href="?op=manage_stages&rota_id=[% rota_id %]">› Manage stages</a> >+ › Edit stage >+[% ELSIF (op == 'create_edit_stage' && !stage.id) %] >+ <a href="?op=manage_stages&rota_id=[% rota_id %]">› Manage stages</a> >+ › Create stage >+[% ELSIF (op == 'manage_items') %] >+ › Manage items >+[% END %] >+ >+</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div id="stockrotation" class="yui-b"> >+ >+ <h1>Stock rotation</h1> >+ >+ [% IF no_op_set %] >+ >+ [% INCLUDE 'stockrotation-toolbar.inc' %] >+ >+ [% IF existing_rotas.size > 0 %] >+ <h3>Manage existing rotas</h3> >+ <table class="rotas_table" role="grid"> >+ <thead> >+ <th>Name</th> >+ <th>Cyclical</th> >+ <th>Active</th> >+ <th>Description</th> >+ <th>Number of items</th> >+ <th> </th> >+ </thead> >+ <tbody> >+ [% FOREACH rota IN existing_rotas %] >+ <tr> >+ <td>[% rota.title %]</td> >+ <td>[% rota.cyclical ? 'Yes' : 'No'%]</td> >+ <td>[% rota.active ? 'Yes' : 'No'%]</td> >+ <td>[% rota.description %]</td> >+ <td>[% rota.stockrotationitems.count %]</td> >+ <td class="actions"> >+ <a class="btn btn-mini" href="?op=create_edit_rota&rota_id=[% rota.rota_id %]"> >+ <i class="fa fa-pencil"></i> >+ Edit >+ </a> >+ <div class="btn-group" role="group"> >+ <button type="button" class="btn btn-mini dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> >+ Manage >+ <i class="fa fa-caret-down"></i> >+ </button> >+ <ul class="dropdown-menu"> >+ <li><a href="?op=manage_stages&rota_id=[% rota.rota_id %]">Stages</a></li> >+ [% IF CAN_user_stockrotation_can_add_items_rotas && rota.stockrotationstages.count > 0 %] >+ <li><a href="?op=manage_items&rota_id=[% rota.rota_id %]">Items</a></li> >+ [% END %] >+ </ul> >+ </div> >+ <a class="btn btn-mini" href="?op=toggle_rota&rota_id=[% rota.rota_id %]"> >+ <i class="fa fa-power-off"></i> >+ [% IF !rota.active %] >+ Activate >+ [% ELSE %] >+ Deactivate >+ [% END %] >+ </a> >+ </td> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ [% END %] >+ >+ [% ELSIF (op == 'create_edit_rota') %] >+ >+ [% IF rota.rota_id %] >+ <h3>Edit "[% rota.title %]"</h3> >+ [% ELSE %] >+ <h3>Create new rota</h3> >+ [% END %] >+ >+ [% IF error == 'invalid_form' %] >+ <div class="dialog alert"> >+ <h3>There was a problem with your form submission</h3> >+ </div> >+ [% END %] >+ >+ <form id="rota_form" method="post" enctype="multipart/form-data" class="validated"> >+ <fieldset class="rows"> >+ <ol> >+ <li> >+ <label class="required" for="title">Name:</label> >+ <input type="text" id="title" name="title" value="[% rota.title %]" required="required" placeholder="Rota name"> >+ <span class="required">Required</span> >+ </li> >+ <li> >+ <label for="cyclical">Cyclical:</label> >+ <select name="cyclical" id="cyclical"> >+ [% IF rota.cyclical %] >+ <option value="1" selected>Yes</option> >+ <option value="0">No</option> >+ [% ELSE %] >+ <option value="1">Yes</option> >+ <option value="0" selected>No</option> >+ [% END %] >+ </select> >+ </li> >+ <li> >+ <label for="active">Active:</label> >+ <select name="active" id="active"> >+ [% IF rota.active %] >+ <option value="1" selected>Yes</option> >+ <option value="0">No</option> >+ [% ELSE %] >+ <option value="1">Yes</option> >+ <option value="0" selected>No</option> >+ [% END %] >+ </select> >+ </li> >+ <li> >+ <label for="description">Description:</label> >+ <textarea id="description" name="description" placeholder="Rota description">[% rota.description %]</textarea> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" value="Submit"> >+ <a href="/cgi-bin/koha/tools/stockrotation.pl" class="cancel">Cancel</a> >+ </fieldset> >+ [% IF rota.rota_id %] >+ <input type="hidden" name="id" value="[% rota.rota_id %]"> >+ [% END %] >+ <input type="hidden" name="op" value="process_rota"> >+ </form> >+ >+ [% ELSIF (op == 'manage_stages') %] >+ >+ [% INCLUDE 'stockrotation-toolbar.inc' %] >+ >+ [% IF existing_stages.size > 0 %] >+ <div id="manage_stages"> >+ <h3>Manage stages</h3> >+ <div id="ajax_status" >+ data-saving-msg="Saving changes..." >+ data-success-msg="" >+ data-failed-msg="Error: "> >+ <span id="ajax_saving_msg"></span> >+ <i id="ajax_saving_icon" class="fa fa-spinner fa-spin"></i> >+ <i id="ajax_success_icon" class="fa fa-check"></i> >+ <i id="ajax_failed_icon" class="fa fa-times"></i> >+ <span id="ajax_success_msg"></span> >+ <span id="ajax_failed_msg"></span> >+ </div> >+ <div id="manage_stages_help"> >+ Stages can be re-ordered by using the <i class="drag_handle fa fa-lg fa-bars"></i>handle to drag and drop them to their new position >+ </div> >+ <div id="stage_list_headings"> >+ <span class="stagename">Branch</span> >+ <span class="stageduration">Duration (days)</span> >+ </div> >+ <ul id="sortable_stages" data-rota-id="[% rota.rota_id %]"> >+ [% FOREACH stage IN existing_stages %] >+ <li id="stage_[% stage.stage_id %]"> >+ <span data-toggle="tooltip" title="Drag and drop to move this stage to another position" data-placement="right" class="stagename"> >+ [% IF existing_stages.size > 1 %] >+ <i class="drag_handle fa fa-lg fa-bars"></i> >+ [% END %] >+ [% Branches.GetName(stage.branchcode_id) %] >+ </span> >+ <span class="stageduration">[% stage.duration %]</span> >+ <span class="stageactions"> >+ <a class="btn btn-mini" href="?op=create_edit_stage&stage_id=[% stage.stage_id %]"> >+ <i class="fa fa-pencil"></i> Edit >+ </a> >+ <a class="btn btn-mini" href="?op=confirm_delete_stage&stage_id=[% stage.stage_id %]"> >+ <i class="fa fa-trash"></i> Delete >+ </a> >+ </span> >+ </li> >+ [% END %] >+ </ul> >+ </div> >+ [% END %] >+ >+ <p><a href="stockrotation.pl">Return to rotas</a></p> >+ >+ [% ELSIF (op == 'create_edit_stage') %] >+ >+ [% IF stage.id %] >+ <h3>Edit "[% Branches.GetName(stage.branchcode_id) %]"</h3> >+ [% ELSE %] >+ <h3>Create new stage</h3> >+ [% END %] >+ >+ [% IF error == 'invalid_form' %] >+ <div class="dialog alert"> >+ <h3>There was a problem with your form submission</h3> >+ </div> >+ [% END %] >+ >+ <form id="stage_form" method="post" enctype="multipart/form-data" class="validated"> >+ <fieldset class="rows"> >+ <ol> >+ <li> >+ <label class="required" for="branch">Branch:</label> >+ <select name="branchcode" id="branch"> >+ [% FOREACH branch IN branches %] >+ [% IF branch.branchcode == stage.branchcode_id %] >+ <option value="[% branch.branchcode %]" selected>[% Branches.GetName(branch.branchcode) %]</option> >+ [% ELSE %] >+ <option value="[% branch.branchcode %]">[% Branches.GetName(branch.branchcode) %]</option> >+ [% END %] >+ [% END %] >+ </select> >+ <span class="required">Required</span> >+ </li> >+ <li> >+ <label class="required" for="duration">Duration:</label> >+ <input type="text" id="duration" name="duration" value="[% stage.duration %]" required="required" placeholder="Duration (days)"> >+ <span class="required">Required</span> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" value="Submit"> >+ <a href="/cgi-bin/koha/tools/stockrotation.pl?op=manage_stages&rota_id=[% rota_id %]" class="cancel">Cancel</a> >+ </fieldset> >+ <input type="hidden" name="stage_id" value="[% stage.id %]"> >+ <input type="hidden" name="rota_id" value="[% rota_id %]"> >+ <input type="hidden" name="op" value="process_stage"> >+ </form> >+ [% ELSIF (op == 'confirm_remove_from_rota') %] >+ >+ <div class="dialog alert"> >+ <h3>Are you sure you wish to remove this item from it's rota</h3> >+ <p> >+ <a class="btn approve" href="?op=remove_item_from_stage&item_id=[% item_id %]&stage_id=[% stage_id %]&rota_id=[% rota_id %]"><i class="fa fa-fw fa-check"></i>Yes</a> >+ <a class="btn deny" href="?op=manage_items&rota_id=[% rota_id %]"><i class="fa fa-fw fa-remove"></i>No</a> >+ </p> >+ </div> >+ [% ELSIF (op == 'confirm_delete_stage') %] >+ >+ <div class="dialog alert"> >+ <h3>Are you sure you want to delete this stage?</h3> >+ [% IF stage.stockrotationitems.count > 0 %] >+ <p>This stage contains the following item(s):</p> >+ <ul> >+ [% FOREACH item IN stage.stockrotationitems %] >+ <li>[% item.itemnumber.biblio.title %] (Barcode: [% item.itemnumber.barcode %])</li> >+ [% END %] >+ </ul> >+ [% END %] >+ <p> >+ <a class="btn approve" href="?op=delete_stage&stage_id=[% stage.stage_id %]"><i class="fa fa-fw fa-check"></i>Yes</a> >+ <a class="btn deny" href="?op=manage_stages&rota_id=[% stage.rota.rota_id %]"><i class="fa fa-fw fa-remove"></i>No</a> >+ </p> >+ </div> >+ [% ELSIF (op == 'manage_items') %] >+ >+ [% INCLUDE 'stockrotation-toolbar.inc' %] >+ >+ [% IF error %] >+ <div class="dialog alert"> >+ [% IF error == "item_not_found" %] >+ <h3>The item was not found</h3> >+ [% ELSIF error == "already_on_rota" %] >+ <h3>This item is already on this rota</h3> >+ [% END %] >+ </div> >+ [% END %] >+ >+ <div> >+ <form id="add_rota_item_form" method="post" enctype="multipart/form-data" class="validated"> >+ <fieldset class="rows"> >+ <legend>Add item to "[% rota.title %]"</legend> >+ <ol> >+ <li> >+ <label for="barcode">Barcode:</label> >+ <input type="text" id="barcode" name="barcode" placeholder="Item barcode" autofocus> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>Use a barcode file</legend> >+ <ol> >+ <li> >+ <label for="barcodefile">Barcode file:</label> >+ <input type="file" id="barcodefile" name="barcodefile"> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" value="Submit"> >+ </fieldset> >+ <input type="hidden" name="rota_id" value="[% rota.id %]"> >+ <input type="hidden" name="op" value="add_items_to_rota"> >+ </form> >+ </div> >+ >+ [% IF items.count > 0 %] >+ <h3>Manage items assigned to "[% rota.title %]"</h3> >+ <table id="sr_manage_items" class="items_table" role="grid"> >+ <thead> >+ <th>Barcode</th> >+ <th>Title</th> >+ <th>Author</th> >+ <th>Shelfmark</th> >+ <th class="NoSearch">In transit</th> >+ <th class="NoSort">Stages & duration in days<br>(current stage highlighted)</th> >+ <th class="NoSort"> </th> >+ </thead> >+ <tbody> >+ [% FOREACH item IN items %] >+ <tr> >+ <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% item.id %]&biblionumber=[% item.itemnumber.biblio.id %]#item[% item.id %]">[% item.itemnumber.barcode %]</a></td> >+ <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% item.itemnumber.biblio.id %]">[% item.itemnumber.biblio.title %]</a></td> >+ <td>[% item.itemnumber.biblio.author %]</td> >+ <td>[% item.itemnumber.itemcallnumber %]</td> >+ <td>[% item.itemnumber.get_transfer ? 'Yes' : 'No' %]</td> >+ <td> >+ [% FOREACH this_stage IN stages %] >+ [% IF this_stage.stage_id == item.stage.stage_id %] >+ <span class="stage highlight_stage"> >+ [% ELSE %] >+ <span class="stage"> >+ [% END %] >+ [% Branches.GetName(this_stage.branchcode_id) %] ([% this_stage.duration %]) >+ </span> >+ » >+ [% END %] >+ [% IF stages.size > 0 %] >+ <span class="stage">[% rota.cyclical ? 'START' : 'END' %]</span> >+ [% END %] >+ </td> >+ <td class="actions"> >+ [% in_transit = item.itemnumber.get_transfer %] >+ [% IF !in_transit && stages.size > 1 %] >+ <a class="btn btn-mini" href="?op=move_to_next_stage&rota_id=[% rota.id %]&item_id=[% item.id %]&stage_id=[% item.stage.stage_id %]"> >+ [% ELSE %] >+ <a class="btn btn-mini" disabled> >+ [% END %] >+ <i class="fa fa-arrow-right"></i> >+ Move to next stage >+ </a> >+ [% IF !in_transit %] >+ <a class="btn btn-mini" href="?op=toggle_in_demand&stage_id=[% item.stage.stage_id %]&item_id=[% item.id %]&rota_id=[% rota.id %]"> >+ [% ELSE %] >+ <a class="btn btn-mini" disabled> >+ [% END %] >+ <i class="fa fa-fire"></i> >+ [% item.indemand ? 'Remove "In demand"' : 'Add "In demand"' %] >+ </a> >+ [% IF !in_transit %] >+ <a class="btn btn-mini" href="?op=confirm_remove_from_rota&stage_id=[% item.stage.stage_id %]&item_id=[% item.id %]&rota_id=[% rota.id %]"> >+ [% ELSE %] >+ <a class="btn btn-mini" disabled> >+ [% END %] >+ <i class="fa fa-trash"></i> >+ Remove from rota >+ </a> >+ </td> >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ [% END %] >+ >+ <p><a href="stockrotation.pl">Return to rotas</a></p> >+ >+ [% ELSIF op == 'add_items_to_rota' %] >+ >+ >+ <div class="dialog message"> >+ <h3>Add items to rota report</h3> >+ </div> >+ <div> >+ [% IF barcode_status.ok.size > 0 %] >+ <h4>Items added to rota:</h4> >+ <ul> >+ [% FOREACH item_ok IN barcode_status.ok %] >+ <li>[% item_ok.biblio.title %]</li> >+ [% END %] >+ </ul> >+ [% END %] >+ [% IF barcode_status.on_this.size > 0 %] >+ <h4>Items already on this rota:</h4> >+ <ul> >+ [% FOREACH item_on_this IN barcode_status.on_this %] >+ <li>[% item_on_this.biblio.title %]</li> >+ [% END %] >+ </ul> >+ [% END %] >+ [% IF barcode_status.not_found.size > 0 %] >+ <h4>Barcodes not found:</h4> >+ <ul> >+ [% FOREACH barcode_not_found IN barcode_status.not_found %] >+ <li>[% barcode_not_found %]</li> >+ [% END %] >+ </ul> >+ [% END %] >+ [% IF barcode_status.on_other.size > 0 %] >+ <h4>Items found on other rotas:</h4> >+ <ul> >+ [% FOREACH item_on_other IN barcode_status.on_other %] >+ <li>[% item_on_other.biblio.title %]</li> >+ [% END %] >+ </ul> >+ [% END %] >+ </div> >+ [% IF barcode_status.on_other.size > 0 %] >+ <form id="add_rota_item_form" method="post" enctype="multipart/form-data"> >+ <fieldset> >+ <legend>Select items to move to this rota:</legend> >+ [% FOREACH item_on_other IN barcode_status.on_other %] >+ <li><input type="checkbox" name="move_item" value="[% item_on_other.itemnumber %]"> [% item_on_other.biblio.title %] (Currently on "[% item_on_other.stockrotationitem.stage.rota.title %]")</li> >+ [% END %] >+ >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" value="Submit"> >+ </fieldset> >+ <input type="hidden" name="rota_id" value="[% rota_id %]"> >+ <input type="hidden" name="op" value="move_items_to_rota"> >+ </form> >+ [% END %] >+ <p><a href="?op=manage_items&rota_id=[% rota_id %]">Return to rota</a></p> >+ >+ [% END %] >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'tools-menu.inc' %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/tools/stockrotation.pl b/tools/stockrotation.pl >new file mode 100755 >index 0000000000..007427078e >--- /dev/null >+++ b/tools/stockrotation.pl >@@ -0,0 +1,519 @@ >+#!/usr/bin/perl >+ >+# Copyright 2016 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+=head1 stockrotation.pl >+ >+ Script to handle stockrotation. Including rotas, their associated stages >+ and items >+ >+=cut >+ >+use Modern::Perl; >+use CGI; >+ >+use C4::Auth; >+use C4::Output; >+ >+use Koha::Libraries; >+use Koha::Stockrotationrotas; >+use Koha::Stockrotationitems; >+use Koha::Stockrotationstages; >+use Koha::Item; >+use Koha::Util::Stockrotation qw(:ALL); >+ >+my $input = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => 'tools/stockrotation.tt', >+ query => $input, >+ type => 'intranet', >+ authnotrequired => 0 >+ } >+); >+ >+# Grab all passed data >+# 'our' since Plack changes the scoping >+# of 'my' >+our %params = $input->Vars(); >+ >+my $op = $params{op}; >+ >+if (!defined $op) { >+ >+ # No operation is supplied, we're just displaying the list of rotas >+ my $rotas = Koha::Stockrotationrotas->search->as_list; >+ >+ $template->param( >+ existing_rotas => $rotas, >+ no_op_set => 1 >+ ); >+ >+} elsif ($op eq 'create_edit_rota') { >+ >+ # Edit an existing rota or define a new one >+ my $rota_id = $params{rota_id}; >+ >+ my $rota = {}; >+ >+ if (!defined $rota_id) { >+ >+ # No ID supplied, we're creating a new rota >+ # Create a shell rota hashref >+ $rota = { >+ cyclical => 1, >+ active => 0 >+ }; >+ >+ } else { >+ >+ # ID supplied, we're editing an existing rota >+ $rota = Koha::Stockrotationrotas->find($rota_id); >+ >+ } >+ >+ $template->param( >+ rota => $rota, >+ op => $op >+ ); >+ >+} elsif ($op eq 'toggle_rota') { >+ >+ # Find and update the active status of the rota >+ my $rota = Koha::Stockrotationrotas->find($params{rota_id}); >+ >+ my $new_active = ($rota->active == 1) ? 0 : 1; >+ >+ $rota->active($new_active)->store; >+ >+ # Return to rotas page >+ print $input->redirect('stockrotation.pl'); >+ >+} elsif ($op eq 'process_rota') { >+ >+ # Get a hashref of the submitted rota data >+ my $rota = get_rota_from_form(); >+ >+ if (!process_rota($rota)) { >+ >+ # The submitted rota was invalid >+ $template->param( >+ error => 'invalid_form', >+ rota => $rota, >+ op => 'create_edit_rota' >+ ); >+ >+ } else { >+ >+ # All was well, return to the rotas list >+ print $input->redirect('stockrotation.pl'); >+ >+ } >+ >+} elsif ($op eq 'manage_stages') { >+ >+ my $rota = Koha::Stockrotationrotas->find($params{rota_id}); >+ >+ $template->param( >+ rota => $rota, >+ branches => get_branches(), >+ existing_stages => get_stages($rota), >+ rota_id => $params{rota_id}, >+ op => $op >+ ); >+ >+} elsif ($op eq 'create_edit_stage') { >+ >+ # Edit an existing stage or define a new one >+ my $stage_id = $params{stage_id}; >+ >+ my $rota_id = $params{rota_id}; >+ >+ if (!defined $stage_id) { >+ >+ # No ID supplied, we're creating a new stage >+ $template->param( >+ branches => get_branches(), >+ stage => {}, >+ rota_id => $rota_id, >+ op => $op >+ ); >+ >+ } else { >+ >+ # ID supplied, we're editing an existing stage >+ my $stage = Koha::Stockrotationstages->find($stage_id); >+ >+ $template->param( >+ branches => get_branches(), >+ stage => $stage, >+ rota_id => $stage->rota->rota_id, >+ op => $op >+ ); >+ >+ } >+ >+} elsif ($op eq 'confirm_remove_from_rota') { >+ >+ # Get the stage we're deleting >+ $template->param( >+ op => $op, >+ rota_id => $params{rota_id}, >+ stage_id => $params{stage_id}, >+ item_id => $params{item_id} >+ ); >+ >+} elsif ($op eq 'confirm_delete_stage') { >+ >+ # Get the stage we're deleting >+ my $stage = Koha::Stockrotationstages->find($params{stage_id}); >+ >+ $template->param( >+ op => $op, >+ stage => $stage >+ ); >+ >+} elsif ($op eq 'delete_stage') { >+ >+ # Get the stage we're deleting >+ my $stage = Koha::Stockrotationstages->find($params{stage_id}); >+ >+ # Get the ID of the rota with which this stage is associated >+ # (so we can return to the "Manage stages" page after deletion) >+ my $rota_id = $stage->rota->rota_id; >+ >+ $stage->delete; >+ >+ # Return to the stages list >+ print $input->redirect("?op=manage_stages&rota_id=$rota_id"); >+ >+} elsif ($op eq 'process_stage') { >+ >+ # Get a hashref of the submitted stage data >+ my $stage = get_stage_from_form(); >+ >+ # The rota we're managing >+ my $rota_id = $params{rota_id}; >+ >+ if (!process_stage($stage, $rota_id)) { >+ >+ # The submitted stage was invalid >+ # Get all branches >+ my $branches = get_branches(); >+ >+ $template->param( >+ error => 'invalid_form', >+ all_branches => $branches, >+ stage => $stage, >+ rota_id => $rota_id, >+ op => 'create_edit_stage' >+ ); >+ >+ } else { >+ >+ # All was well, return to the stages list >+ print $input->redirect("?op=manage_stages&rota_id=$rota_id"); >+ >+ } >+ >+} elsif ($op eq 'manage_items') { >+ >+ my $rota = Koha::Stockrotationrotas->find($params{rota_id}); >+ >+ # Get all items on this rota, for each prefetch their >+ # stage and biblio objects >+ my $items = Koha::Stockrotationitems->search( >+ { 'stage.rota_id' => $params{rota_id} }, >+ { >+ prefetch => { >+ stage => { >+ 'stockrotationitems' => { >+ 'itemnumber' => 'biblionumber' >+ } >+ } >+ } >+ } >+ ); >+ >+ $template->param( >+ rota_id => $params{rota_id}, >+ error => $params{error}, >+ items => $items, >+ branches => get_branches(), >+ stages => get_stages($rota), >+ rota => $rota, >+ op => $op >+ ); >+ >+} elsif ($op eq 'move_to_next_stage') { >+ >+ move_to_next_stage($params{item_id}, $params{stage_id}); >+ >+ # Return to the items list >+ print $input->redirect("?op=manage_items&rota_id=" . $params{rota_id}); >+ >+} elsif ($op eq 'toggle_in_demand') { >+ >+ # Toggle the item's in_demand >+ toggle_indemand($params{item_id}, $params{stage_id}); >+ >+ # Return to the items list >+ print $input->redirect("?op=manage_items&rota_id=".$params{rota_id}); >+ >+} elsif ($op eq 'remove_item_from_stage') { >+ >+ # Remove the item from the stage >+ remove_from_stage($params{item_id}, $params{stage_id}); >+ >+ # Return to the items list >+ print $input->redirect("?op=manage_items&rota_id=".$params{rota_id}); >+ >+} elsif ($op eq 'add_items_to_rota') { >+ >+ # The item's barcode, >+ # which we may or may not have been passed >+ my $barcode = $params{barcode}; >+ >+ # The rota we're adding the item to >+ my $rota_id = $params{rota_id}; >+ >+ # The uploaded file filehandle, >+ # which we may or may not have been passed >+ my $barcode_file = $input->upload("barcodefile"); >+ >+ # We need to create an array of one or more barcodes to >+ # insert >+ my @barcodes = (); >+ >+ # If the barcode input box was populated, use it >+ push @barcodes, $barcode if $barcode; >+ >+ # Only parse the uploaded file if necessary >+ if ($barcode_file) { >+ >+ # Call binmode on the filehandle as we want to set a >+ # UTF-8 layer on it >+ binmode($barcode_file, ":encoding(UTF-8)"); >+ # Parse the file into an array of barcodes >+ while (my $barcode = <$barcode_file>) { >+ $barcode =~ s/\r/\n/g; >+ $barcode =~ s/\n+/\n/g; >+ my @data = split(/\n/, $barcode); >+ push @barcodes, @data; >+ } >+ >+ } >+ >+ # A hashref to hold the status of each barcode >+ my $barcode_status = { >+ ok => [], >+ on_other => [], >+ on_this => [], >+ not_found => [] >+ }; >+ >+ # If we have something to work with, do it >+ get_barcodes_status($rota_id, \@barcodes, $barcode_status) if (@barcodes); >+ >+ # Now we know the status of each barcode, add those that >+ # need it >+ if (scalar @{$barcode_status->{ok}} > 0) { >+ >+ add_items_to_rota($rota_id, $barcode_status->{ok}); >+ >+ } >+ # If we were only passed one barcode and it was successfully >+ # added, redirect back to ourselves, we don't want to display >+ # a report, redirect also if we were passed no barcodes >+ if ( >+ scalar @barcodes == 0 || >+ (scalar @barcodes == 1 && scalar @{$barcode_status->{ok}} == 1) >+ ) { >+ >+ print $input->redirect("?op=manage_items&rota_id=$rota_id"); >+ >+ } else { >+ >+ # Report on the outcome >+ $template->param( >+ barcode_status => $barcode_status, >+ rota_id => $rota_id, >+ op => $op >+ ); >+ >+ } >+ >+} elsif ($op eq 'move_items_to_rota') { >+ >+ # The barcodes of the items we're moving >+ my @move = $input->param('move_item'); >+ >+ foreach my $item(@move) { >+ >+ # The item we're moving >+ my $item = Koha::Items->find($item); >+ >+ # Move it to the new rota >+ $item->add_to_rota($params{rota_id}); >+ >+ } >+ >+ # Return to the items list >+ print $input->redirect("?op=manage_items&rota_id=".$params{rota_id}); >+ >+} >+ >+output_html_with_http_headers $input, $cookie, $template->output; >+ >+sub get_rota_from_form { >+ >+ return { >+ id => $params{id}, >+ title => $params{title}, >+ cyclical => $params{cyclical}, >+ active => $params{active}, >+ description => $params{description} >+ }; >+} >+ >+sub get_stage_from_form { >+ >+ return { >+ stage_id => $params{stage_id}, >+ branchcode => $params{branchcode}, >+ duration => $params{duration} >+ }; >+} >+ >+sub process_rota { >+ >+ my $sub_rota = shift; >+ >+ # Fields we require >+ my @required = ('title','cyclical','active'); >+ >+ # Count of the number of required fields we have >+ my $valid = 0; >+ >+ # Ensure we have everything we require >+ foreach my $req(@required) { >+ >+ if (exists $sub_rota->{$req}) { >+ >+ chomp(my $value = $sub_rota->{$req}); >+ if (length $value > 0) { >+ $valid++; >+ } >+ >+ } >+ >+ } >+ >+ # If we don't have everything we need >+ return 0 if $valid != scalar @required; >+ >+ # Passed validation >+ # Find the rota we're updating >+ my $rota = Koha::Stockrotationrotas->find($sub_rota->{id}); >+ >+ if ($rota) { >+ >+ $rota->title( >+ $sub_rota->{title} >+ )->cyclical( >+ $sub_rota->{cyclical} >+ )->active( >+ $sub_rota->{active} >+ )->description( >+ $sub_rota->{description} >+ )->store; >+ >+ } else { >+ >+ $rota = Koha::Stockrotationrota->new({ >+ title => $sub_rota->{title}, >+ cyclical => $sub_rota->{cyclical}, >+ active => $sub_rota->{active}, >+ description => $sub_rota->{description} >+ })->store; >+ >+ } >+ >+ return 1; >+} >+ >+sub process_stage { >+ >+ my ($sub_stage, $rota_id) = @_; >+ >+ # Fields we require >+ my @required = ('branchcode','duration'); >+ >+ # Count of the number of required fields we have >+ my $valid = 0; >+ >+ # Ensure we have everything we require >+ foreach my $req(@required) { >+ >+ if (exists $sub_stage->{$req}) { >+ >+ chomp(my $value = $sub_stage->{$req}); >+ if (length $value > 0) { >+ $valid++; >+ } >+ >+ } >+ >+ } >+ >+ # If we don't have everything we need >+ return 0 if $valid != scalar @required; >+ >+ # Passed validation >+ # Find the stage we're updating >+ my $stage = Koha::Stockrotationstages->find($sub_stage->{stage_id}); >+ >+ if ($stage) { >+ >+ # Updating an existing stage >+ $stage->branchcode_id( >+ $sub_stage->{branchcode} >+ )->duration( >+ $sub_stage->{duration} >+ )->store; >+ >+ } else { >+ >+ # Creating a new stage >+ $stage = Koha::Stockrotationstage->new({ >+ branchcode_id => $sub_stage->{branchcode}, >+ rota_id => $rota_id, >+ duration => $sub_stage->{duration} >+ })->store; >+ >+ } >+ >+ return 1; >+} >+ >+=head1 AUTHOR >+ >+Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >+ >+=cut >-- >2.12.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 11897
:
25887
|
58207
|
58208
|
58209
|
58210
|
58211
|
58212
|
58213
|
58214
|
58215
|
58216
|
58217
|
58218
|
58219
|
58280
|
58281
|
58687
|
58692
|
58693
|
58694
|
58695
|
58696
|
60175
|
60715
|
61825
|
61826
|
61827
|
61828
|
61829
|
61830
|
61831
|
61832
|
61833
|
61834
|
61835
|
61836
|
61837
|
61838
|
61839
|
61885
|
62730
|
62750
|
62751
|
62752
|
62753
|
62754
|
62755
|
62756
|
62757
|
62758
|
62759
|
62760
|
62761
|
62762
|
62763
|
62764
|
62765
|
62766
|
62767
|
63063
|
63064
|
63065
|
63066
|
63067
|
63068
|
63069
|
63070
|
63071
|
63072
|
63073
|
63074
|
63075
|
63076
|
63077
|
63078
|
63079
|
63080
|
63114
|
64850
|
64851
|
65715
|
65716
|
65717
|
65718
|
65719
|
65720
|
65721
|
65722
|
65723
|
65724
|
65725
|
65726
|
65727
|
65728
|
65729
|
65730
|
65731
|
65732
|
65733
|
65734
|
65735
|
65736
|
65737
|
65738
|
65739
|
65740
|
65741
|
65742
|
65743
|
65744
|
65745
|
65746
|
65747
|
65748
|
65749
|
65750
|
65751
|
65752
|
65753
|
65754
|
65755
|
65756
|
65757
|
65758
|
66381
|
70496
|
70497
|
70498
|
70499
|
70500
|
70501
|
70502
|
70503
|
70504
|
70505
|
70506
|
70507
|
70508
|
70509
|
70510
|
70511
|
70512
|
70513
|
70514
|
70515
|
70516
|
70517
|
70518
|
70519
|
70520
|
70521
|
70522
|
70523
|
70524
|
72124
|
72125
|
72126
|
72127
|
72128
|
74003
|
74004
|
74005
|
74006
|
74007
|
74008
|
74010
|
74011
|
74012
|
74013
|
74014
|
74015
|
74016
|
74017
|
74197
|
74198
|
74199
|
74200
|
74201
|
74202
|
74203
|
74204
|
74205
|
74206
|
74319
|
74320
|
74360
|
74459
|
74460
|
74461
|
74462
|
74463
|
74464
|
74465
|
74466
|
74467
|
74468
|
74469
|
74470
|
75409
|
75410
|
75411
|
75412
|
75413
|
75414
|
75415
|
75416
|
75417
|
75418
|
75419
|
75420
|
76121
|
76122
|
76123
|
76124
|
76125
|
76126
|
76127
|
76128
|
76129
|
76130
|
76131
|
76132
|
76133
|
76134
|
76135
|
76144
|
76706
|
76707
|
76708
|
76709
|
76710
|
77623
|
77624
|
77625
|
77626
|
78387
|
78388
|
78389
|
78390
|
78391
|
78392
|
78393
|
78394
|
78404
|
78405
|
78406
|
78407
|
78408
|
79040
|
79041
|
79042
|
79043
|
79044
|
79738
|
79739
|
79740
|
79741
|
79742
|
79746
|
79747
|
79748
|
79749
|
79750
|
79964
|
79965
|
79966
|
79967
|
79968
|
79969
|
79970
|
79971
|
79972
|
79973
|
79974
|
79975
|
80068
|
80087
|
80088
|
80089
|
80090
|
80091
|
80092
|
80093
|
80094
|
80095
|
80096
|
80097
|
80098
|
80099
|
80100
|
80118
|
80260
|
80261
|
80262
|
80263
|
80264
|
80265
|
80266
|
80267
|
80268
|
80269
|
80270
|
80271
|
80272
|
80273
|
80274
|
80275
|
80289
|
80298
|
80299
|
80300