From a171544a52a491564ee4c50c60bfae2381abe833 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 13 Mar 2019 07:09:15 -0400 Subject: [PATCH] Bug 14697: Extend and enhance "Claims returned" lost status This adds a "Claims returned" feature that extends and enhances the claims returned lost status Test Plan: 1) Create a "Claims Returned" lost value 2) Create some RETURN_CLAIM_RESOLUTION authorized values 3) Set ClaimReturnedLostValue 4) Set ClaimReturnedChargeFee 5) Set ClaimReturnedWarningThreshold 6) Create some checkouts 7) Claim some returns 8) Verify ClaimReturnedChargeFee works with all 3 options 9) Verify ClaimReturnedWarningThreshold shows a warning once the threshold has been exceeded 10) Edit notes on a claim 11) Resolve a claim 12) Delete a claim --- Koha/Checkout.pm | 45 ++- Koha/Checkouts/ReturnClaim.pm | 65 ++++ Koha/Checkouts/ReturnClaims.pm | 86 +++++ Koha/Patron.pm | 12 + Koha/REST/V1/ReturnClaims.pm | 212 +++++++++++ api/v1/swagger/definitions.json | 3 + api/v1/swagger/definitions/return_claim.json | 90 +++++ api/v1/swagger/paths.json | 12 + api/v1/swagger/paths/return_claims.json | 358 ++++++++++++++++++ .../data/mysql/atomicupdate/bug_14697.perl | 2 +- .../prog/en/includes/checkouts-table.inc | 71 ++++ .../prog/en/includes/patron-return-claims.inc | 15 + .../prog/en/includes/strings.inc | 5 + .../admin/preferences/circulation.pref | 19 + .../prog/en/modules/catalogue/moredetail.tt | 36 +- .../prog/en/modules/circ/circulation.tt | 35 ++ .../prog/en/modules/members/moremember.tt | 24 ++ koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 274 +++++++++++++- svc/checkouts | 61 ++- svc/return_claims | 127 +++++++ t/db_dependent/api/v1/return_claims.t | 159 ++++++++ 21 files changed, 1673 insertions(+), 38 deletions(-) create mode 100644 Koha/Checkouts/ReturnClaim.pm create mode 100644 Koha/Checkouts/ReturnClaims.pm create mode 100644 Koha/REST/V1/ReturnClaims.pm create mode 100644 api/v1/swagger/definitions/return_claim.json create mode 100644 api/v1/swagger/paths/return_claims.json create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/patron-return-claims.inc create mode 100755 svc/return_claims create mode 100644 t/db_dependent/api/v1/return_claims.t diff --git a/Koha/Checkout.pm b/Koha/Checkout.pm index b7a752cdc5..51aebcabba 100644 --- a/Koha/Checkout.pm +++ b/Koha/Checkout.pm @@ -21,9 +21,10 @@ package Koha::Checkout; use Modern::Perl; use Carp; +use DateTime; +use Koha::Checkouts::ReturnClaims; use Koha::Database; -use DateTime; use Koha::DateUtils; use Koha::Items; @@ -88,6 +89,48 @@ sub patron { return Koha::Patron->_new_from_dbic( $patron_rs ); } +=head3 claim_returned + +my $return_claim = $checkout->claim_returned(); + +=cut + +sub claim_returned { + my ( $self, $params ) = @_; + + my $notes = $params->{notes}; + my $charge_lost_fee = $params->{charge_lost_fee}; + my $created_by = $params->{created_by}; + + $created_by ||= C4::Context->userenv->{number} if C4::Context->userenv; + + my $claim = Koha::Checkouts::ReturnClaims->find( { issue_id => $self->id } ); + $claim ||= Koha::Checkouts::ReturnClaims->find( { old_issue_id => $self->id } ); + + $claim ||= Koha::Checkouts::ReturnClaim->new( + { + issue_id => $self->id, + itemnumber => $self->itemnumber, + borrowernumber => $self->borrowernumber, + notes => $notes, + created_on => dt_from_string, + created_by => $created_by, + } + )->store(); + + my $ClaimReturnedLostValue = C4::Context->preference('ClaimReturnedLostValue'); + C4::Items::ModItem( { itemlost => $ClaimReturnedLostValue }, undef, $self->itemnumber ); + + my $ClaimReturnedChargeFee = C4::Context->preference('ClaimReturnedChargeFee'); + $charge_lost_fee = + $ClaimReturnedChargeFee eq 'charge' ? 1 + : $ClaimReturnedChargeFee eq 'no_charge' ? 0 + : $charge_lost_fee; # $ClaimReturnedChargeFee eq 'ask' + C4::Circulation::LostItem( $self->itemnumber, 'claim_returned' ) if $charge_lost_fee; + + return $claim; +} + =head3 type =cut diff --git a/Koha/Checkouts/ReturnClaim.pm b/Koha/Checkouts/ReturnClaim.pm new file mode 100644 index 0000000000..3fff2e6608 --- /dev/null +++ b/Koha/Checkouts/ReturnClaim.pm @@ -0,0 +1,65 @@ +package Koha::Checkouts::ReturnClaim; + +# Copyright ByWater Solutions 2019 +# +# 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. + +use Modern::Perl; + +use base qw(Koha::Object); + +use Koha::Checkouts; +use Koha::Old::Checkouts; + +=head1 NAME + +Koha::Checkouts::ReturnClaim - Koha ReturnClaim object class + +=head1 API + +=head2 Class Methods + +=cut + +=head3 checkout + +=cut + +sub checkout { + my ( $self ) = @_; + + my $issue = $self->_result->issue; + return Koha::Checkout->_new_from_dbic( $issue ) if $issue; + + my $old_issue = $self->_result->old_issue; + return Koha::Old::Checkout->_new_from_dbic( $old_issue ) if $old_issue; +} + +=head3 _type + +=cut + +sub _type { + return 'ReturnClaim'; +} + +=head1 AUTHOR + +Kyle M Hall + +=cut + +1; diff --git a/Koha/Checkouts/ReturnClaims.pm b/Koha/Checkouts/ReturnClaims.pm new file mode 100644 index 0000000000..414416ba68 --- /dev/null +++ b/Koha/Checkouts/ReturnClaims.pm @@ -0,0 +1,86 @@ +package Koha::Checkouts::ReturnClaims; + +# Copyright ByWater Solutions 2019 +# +# 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. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use Koha::Checkouts::ReturnClaim; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::Checkouts::ReturnClaims - Koha ReturnClaim object set class + +=head1 API + +=head2 Class Methods + +=cut + +=head3 unresolved + +=cut + +sub unresolved { + my ($self) = @_; + + my $results = $self->_resultset()->search_rs( { resolved_on => undef } ); + + return Koha::Checkouts::ReturnClaims->_new_from_dbic( $results ); +} + +=head3 resolved + +=cut + +sub resolved { + my ($self) = @_; + + my $results = $self->_resultset()->search_rs( { resolved_on => { '!=' => undef } } ); + + return Koha::Checkouts::ReturnClaims->_new_from_dbic( $results ); +} + +=head3 type + +=cut + +sub _type { + return 'ReturnClaim'; +} + +=head3 object_class + +=cut + +sub object_class { + return 'Koha::Checkouts::ReturnClaim'; +} + +=head1 AUTHOR + +Kyle M Hall + +=cut + +1; diff --git a/Koha/Patron.pm b/Koha/Patron.pm index 436120e0e6..1040c70179 100644 --- a/Koha/Patron.pm +++ b/Koha/Patron.pm @@ -1072,6 +1072,18 @@ sub old_holds { return Koha::Old::Holds->_new_from_dbic($old_holds_rs); } +=head3 return_claims + +my $return_claims = $patron->return_claims + +=cut + +sub return_claims { + my ($self) = @_; + my $return_claims = $self->_result->return_claims_borrowernumbers; + return Koha::Checkouts::ReturnClaims->_new_from_dbic( $return_claims ); +} + =head3 notice_email_address my $email = $patron->notice_email_address; diff --git a/Koha/REST/V1/ReturnClaims.pm b/Koha/REST/V1/ReturnClaims.pm new file mode 100644 index 0000000000..b1c080f311 --- /dev/null +++ b/Koha/REST/V1/ReturnClaims.pm @@ -0,0 +1,212 @@ +package Koha::REST::V1::ReturnClaims; + +# 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. + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Checkouts::ReturnClaims; +use Koha::Checkouts; +use Koha::DateUtils qw( dt_from_string output_pref ); + +=head1 NAME + +Koha::REST::V1::ReturnClaims + +=head2 Operations + +=head3 claim_returned + +Claim that a checked out item was returned. + +=cut + +sub claim_returned { + my $c = shift->openapi->valid_input or return; + my $input = $c->validation->output; + my $body = $c->validation->param('body'); + + my $itemnumber = $input->{item_id}; + my $charge_lost_fee = $body->{charge_lost_fee} ? 1 : 0; + my $created_by = $body->{created_by}; + my $notes = $body->{notes}; + + my $checkout = Koha::Checkouts->find( { itemnumber => $itemnumber } ); + + return $c->render( + openapi => { error => "Not found - Checkout not found" }, + status => 404 + ) unless $checkout; + + my $claim = Koha::Checkouts::ReturnClaims->find( + { + issue_id => $checkout->id + } + ); + return $c->render( + openapi => { error => "Bad request - claim exists" }, + status => 400 + ) if $claim; + + $claim = $checkout->claim_returned( + { + charge_lost_fee => $charge_lost_fee, + created_by => $created_by, + notes => $notes, + } + ); + + my $data = $claim->unblessed; + + my $c_dt = dt_from_string( $data->{created_on} ); + my $u_dt = dt_from_string( $data->{updated_on} ); + + $data->{created_on_formatted} = output_pref( { dt => $c_dt } ); + $data->{updated_on_formatted} = output_pref( { dt => $u_dt } ); + + $data->{created_on} = $c_dt->iso8601; + $data->{updated_on} = $u_dt->iso8601; + + return $c->render( openapi => $data, status => 200 ); +} + +=head3 update_notes + +Update the notes of an existing claim + +=cut + +sub update_notes { + my $c = shift->openapi->valid_input or return; + my $input = $c->validation->output; + my $body = $c->validation->param('body'); + + my $id = $input->{claim_id}; + my $updated_by = $body->{updated_by}; + my $notes = $body->{notes}; + + $updated_by ||= + C4::Context->userenv ? C4::Context->userenv->{number} : undef; + + my $claim = Koha::Checkouts::ReturnClaims->find($id); + + return $c->render( + openapi => { error => "Not found - Claim not found" }, + status => 404 + ) unless $claim; + + $claim->set( + { + notes => $notes, + updated_by => $updated_by, + updated_on => dt_from_string(), + } + ); + $claim->store(); + + my $data = $claim->unblessed; + + my $c_dt = dt_from_string( $data->{created_on} ); + my $u_dt = dt_from_string( $data->{updated_on} ); + + $data->{created_on_formatted} = output_pref( { dt => $c_dt } ); + $data->{updated_on_formatted} = output_pref( { dt => $u_dt } ); + + $data->{created_on} = $c_dt->iso8601; + $data->{updated_on} = $u_dt->iso8601; + + return $c->render( openapi => $data, status => 200 ); +} + +=head3 resolve_claim + +Marks a claim as resolved + +=cut + +sub resolve_claim { + my $c = shift->openapi->valid_input or return; + my $input = $c->validation->output; + my $body = $c->validation->param('body'); + + my $id = $input->{claim_id}; + my $resolved_by = $body->{updated_by}; + my $resolution = $body->{resolution}; + + $resolved_by ||= + C4::Context->userenv ? C4::Context->userenv->{number} : undef; + + my $claim = Koha::Checkouts::ReturnClaims->find($id); + + return $c->render( + openapi => { error => "Not found - Claim not found" }, + status => 404 + ) unless $claim; + + $claim->set( + { + resolution => $resolution, + resolved_by => $resolved_by, + resolved_on => dt_from_string(), + } + ); + $claim->store(); + + my $data = $claim->unblessed; + + my $c_dt = dt_from_string( $data->{created_on} ); + my $u_dt = dt_from_string( $data->{updated_on} ); + my $r_dt = dt_from_string( $data->{resolved_on} ); + + $data->{created_on_formatted} = output_pref( { dt => $c_dt } ); + $data->{updated_on_formatted} = output_pref( { dt => $u_dt } ); + $data->{resolved_on_formatted} = output_pref( { dt => $r_dt } ); + + $data->{created_on} = $c_dt->iso8601; + $data->{updated_on} = $u_dt->iso8601; + $data->{resolved_on} = $r_dt->iso8601; + + return $c->render( openapi => $data, status => 200 ); +} + +=head3 delete_claim + +Deletes the claim from the database + +=cut + +sub delete_claim { + my $c = shift->openapi->valid_input or return; + my $input = $c->validation->output; + + my $id = $input->{claim_id}; + + my $claim = Koha::Checkouts::ReturnClaims->find($id); + + return $c->render( + openapi => { error => "Not found - Claim not found" }, + status => 404 + ) unless $claim; + + $claim->delete(); + + my $data = $claim->unblessed; + + return $c->render( openapi => $data, status => 200 ); +} + +1; diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index 4ac42cf925..90374145a7 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -43,5 +43,8 @@ }, "fund": { "$ref": "definitions/fund.json" + }, + "return_claim": { + "$ref": "definitions/return_claim.json" } } diff --git a/api/v1/swagger/definitions/return_claim.json b/api/v1/swagger/definitions/return_claim.json new file mode 100644 index 0000000000..8dc63ffae8 --- /dev/null +++ b/api/v1/swagger/definitions/return_claim.json @@ -0,0 +1,90 @@ +{ + "type": "object", + "properties": { + "id": { + "type": [ + "integer" + ], + "description": "internally assigned return claim identifier" + }, + "item_id": { + "type": [ + "integer" + ], + "description": "internal identifier of the claimed item" + }, + "issue_id": { + "type": [ + "integer", + "null" + ], + "description": "internal identifier of the claimed checkout if still checked out" + }, + "old_issue_id": { + "type": [ + "integer", + "null" + ], + "description": "internal identifier of the claimed checkout if not longer checked out" + }, + "patron_id": { + "$ref": "../x-primitives.json#/patron_id" + }, + "notes": { + "type": [ + "string", + "null" + ], + "description": "notes about this claim" + }, + "created_on": { + "type": [ + "string", + "null" + ], + "description": "date of claim creation" + }, + "created_by": { + "type": [ + "integer", + "null" + ], + "description": "patron id of librarian who made the claim" + }, + "updated_on": { + "type": [ + "string", + "null" + ], + "description": "date the claim was last updated" + }, + "updated_by": { + "type": [ + "integer", + "null" + ], + "description": "patron id of librarian who last updated the claim" + }, + "resolution": { + "type": [ + "string", + "null" + ], + "description": "code of resolution type for this claim" + }, + "resolved_on": { + "type": [ + "string", + "null" + ], + "description": "date the claim was resolved" + }, + "resolved_by": { + "type": [ + "integer", + "null" + ], + "description": "patron id of librarian who resolved this claim" + } + } +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index 946de0a6a4..4e11c9bf06 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -73,5 +73,17 @@ }, "/public/patrons/{patron_id}/password": { "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1password" + }, + "/return_claims/claim/{item_id}/": { + "$ref": "paths/return_claims.json#/~1return_claims~1claim~1{item_id}" + }, + "/return_claims/{claim_id}/notes": { + "$ref": "paths/return_claims.json#/~1return_claims~1{claim_id}~1notes" + }, + "/return_claims/{claim_id}/resolve": { + "$ref": "paths/return_claims.json#/~1return_claims~1{claim_id}~1resolve" + }, + "/return_claims/{claim_id}": { + "$ref": "paths/return_claims.json#/~1return_claims~1{claim_id}" } } diff --git a/api/v1/swagger/paths/return_claims.json b/api/v1/swagger/paths/return_claims.json new file mode 100644 index 0000000000..0289857672 --- /dev/null +++ b/api/v1/swagger/paths/return_claims.json @@ -0,0 +1,358 @@ +{ + "/return_claims/claim/{item_id}": { + "post": { + "x-mojo-to": "ReturnClaims#claim_returned", + "operationId": "claimReturned", + "tags": [ + "claims", + "returned", + "return", + "claim" + ], + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": true, + "description": "Itemnumber of item to claim as returned", + "type": "integer" + }, + { + "name": "body", + "in": "body", + "description": "A JSON object containing fields to modify", + "required": true, + "schema": { + "type": "object", + "properties": { + "notes": { + "description": "Notes about this return claim", + "type": "string" + }, + "created_by": { + "description": "User id for the librarian submitting this claim", + "type": "string" + }, + "charge_lost_fee": { + "description": "Charge a lost fee if true and Koha is set to allow a choice. Ignored otherwise.", + "type": "boolean" + } + } + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Created claim", + "schema": { + "$ref": "../definitions.json#/return_claim" + } + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Checkout not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "circulate": "circulate_remaining_permissions" + } + } + } + }, + "/return_claims/{claim_id}/notes": { + "put": { + "x-mojo-to": "ReturnClaims#update_notes", + "operationId": "updateClaimNotes", + "tags": [ + "claims", + "returned", + "return", + "claim", + "notes" + ], + "parameters": [ + { + "name": "claim_id", + "in": "path", + "required": true, + "description": "Unique identifier for the claim whose notes are to be updated", + "type": "integer" + }, + { + "name": "body", + "in": "body", + "description": "A JSON object containing fields to modify", + "required": true, + "schema": { + "type": "object", + "properties": { + "notes": { + "description": "Notes about this return claim", + "type": "string" + }, + "updated_by": { + "description": "User id for the librarian updating the claim notes", + "type": "string" + } + } + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Claim notes updated", + "schema": { + "$ref": "../definitions.json#/return_claim" + } + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Claim not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "circulate": "circulate_remaining_permissions" + } + } + } + }, + "/return_claims/{claim_id}": { + "delete": { + "x-mojo-to": "ReturnClaims#delete_claim", + "operationId": "deletedClaim", + "tags": [ + "claims", + "returned", + "return", + "claim", + "delete" + ], + "parameters": [ + { + "name": "claim_id", + "in": "path", + "required": true, + "description": "Unique identifier for the claim to be deleted", + "type": "integer" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Claim deleted", + "schema": { + "$ref": "../definitions.json#/return_claim" + } + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Claim not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "circulate": "circulate_remaining_permissions" + } + } + } + }, + "/return_claims/{claim_id}/resolve": { + "put": { + "x-mojo-to": "ReturnClaims#resolve_claim", + "operationId": "updateClaimResolve", + "tags": [ + "claims", + "returned", + "return", + "claim", + "notes" + ], + "parameters": [ + { + "name": "claim_id", + "in": "path", + "required": true, + "description": "Unique identifier for the claim to be resolved", + "type": "integer" + }, + { + "name": "body", + "in": "body", + "description": "A JSON object containing fields to modify", + "required": true, + "schema": { + "type": "object", + "properties": { + "resolution": { + "description": "The RETURN_CLAIM_RESOLUTION code to be used to resolve the calim", + "type": "string" + }, + "resolved_by": { + "description": "User id for the librarian resolving the claim", + "type": "string" + } + } + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Claim resolved", + "schema": { + "$ref": "../definitions.json#/return_claim" + } + }, + "400": { + "description": "Bad request", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Claim not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "circulate": "circulate_remaining_permissions" + } + } + } + } +} diff --git a/installer/data/mysql/atomicupdate/bug_14697.perl b/installer/data/mysql/atomicupdate/bug_14697.perl index 16cf82ad90..411f6249d2 100644 --- a/installer/data/mysql/atomicupdate/bug_14697.perl +++ b/installer/data/mysql/atomicupdate/bug_14697.perl @@ -30,7 +30,7 @@ if( CheckVersion( $DBversion ) ) { } $dbh->do(q{ - INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES + INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('ClaimReturnedChargeFee', 'ask', 'ask|charge|no_charge', 'Controls whether or not a lost item fee is charged for return claims', 'Choice'), ('ClaimReturnedLostValue', '', '', 'Sets the LOST AV value that represents "Claims returned" as a lost value', 'Free'), ('ClaimReturnedWarningThreshold', '', '', 'Sets the number of return claims past which the librarian will be warned the patron has many return claims', 'Integer'); diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc index 1276e70ab1..f1bc60ff4b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc @@ -28,6 +28,7 @@ Price Renew

select all | none

Check in

select all | none

+ Return claims Export

select all | none

@@ -83,3 +84,73 @@

Patron has nothing checked out.

[% END %] + + + + + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/patron-return-claims.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-return-claims.inc new file mode 100644 index 0000000000..63f1dad303 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-return-claims.inc @@ -0,0 +1,15 @@ +
+ + + + + + + + + + + + +
Claim IDTitleNotesCreated onUpdated onResolution 
+
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc index eb7bfda139..781f7ae245 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc @@ -5,6 +5,10 @@ var NOT_RENEWABLE_RESTRICTION = _("Not allowed: patron restricted"); var CIRCULATION_RENEWED_DUE = _("Renewed, due:"); var CIRCULATION_RENEW_FAILED = _("Renew failed:"); + var RETURN_CLAIMED = _("Return claimed"); + var RETURN_CLAIMED_FAILURE = _("Unable to claim as returned"); + var RETURN_CLAIMED_MAKE = _("Claim returned"); + var RETURN_CLAIMED_NOTES = _("Notes about return claim"); var NOT_CHECKED_OUT = _("not checked out"); var TOO_MANY_RENEWALS = _("too many renewals"); var ON_RESERVE = _("on hold"); @@ -46,4 +50,5 @@ var CURRENT = _(" (current) "); var MSG_NO_ITEMTYPE = _("No itemtype"); var MSG_CHECKOUTS_BY_ITEMTYPE = _("Number of checkouts by item type"); + var CONFIRM_DELETE_RETURN_CLAIM = _("Are you sure you want to delete this return claim?"); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 199809f139..2e9e0ba1ac 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -1080,3 +1080,22 @@ Circulation: pages: Pages chapters: Chapters - + Return Claims: + - + - When marking a checkout as "claims returned", + - pref: ClaimReturnedChargeFee + default: ask + choices: + ask: ask if a lost fee should be charged + charge: charge a lost fee + no_charge: don't charge a lost fee + - . + - + - Use the LOST authorised value + - pref: ClaimReturnedLostValue + - to represent returns claims + - + - Warn librarians that a patron has excessive return cliams if the patron has claimed the return of more than + - pref: ClaimReturnedWarningThreshold + class: integer + - items. diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt index 777f86667b..0e42df20c2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt @@ -100,22 +100,30 @@
  • Lost status: [% IF ( CAN_user_circulate ) %]
    - - - - + + + + + + + [% SET ClaimReturnedLostValue = Koha.Preference('ClaimReturnedLostValue') %] + [% IF ClaimReturnedLostValue && ITEM_DAT.itemlost == ClaimReturnedLostValue %] + +

    Item has been claimed as returned.

    [% ELSE %] - + [% END %] - [% END %] - - - -
    + [% ELSE %] [% FOREACH itemlostloo IN itemlostloop %] [% IF ( itemlostloo.selected ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 5fb4889bed..d8df89b125 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -728,6 +728,12 @@
  • Overdues: Patron has ITEMS OVERDUE. See highlighted items below
  • [% END %] + [% SET ClaimReturnedWarningThreshold = Koha.Preference('ClaimReturnedWarningThreshold') %] + [% SET return_claims = patron.return_claims %] + [% IF return_claims.count %] +
  • Return claims: Patron has [% return_claims.count | html %] RETURN CLAIMS. + [% END %] + [% IF ( charges ) %] [% INCLUDE 'blocked-fines.inc' fines = chargesamount %] [% END %] @@ -841,6 +847,30 @@
  • [% END %] +
  • + [% IF ( patron.return_claims.count ) %] + + [% patron.return_claims.resolved.count | html %] + / + [% patron.return_claims.unresolved.count | html %] + Claim(s) + + [% ELSE %] + + 0 + / + 0 + Claim(s) + + [% END %] +
  • + + [% IF Koha.Preference('ArticleRequests') %] +
  • + [% patron.article_requests_current.count | html %] Article requests +
  • + [% END %] +
  • [% debarments.count | html %] Restrictions
  • [% SET enrollments = patron.get_club_enrollments(1) %] @@ -924,6 +954,8 @@ [% END # /IF holds_count %] + [% INCLUDE 'patron-return-claims.inc' %] + [% IF Koha.Preference('ArticleRequests') %] [% INCLUDE 'patron-article-requests.inc' %] [% END %] @@ -991,6 +1023,9 @@ [% Asset.js("js/circ-patron-search-results.js") | $raw %]