Bugzilla – Attachment 151213 Details for
Bug 29002
Add ability to book items ahead of time
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 29002: Add Booking objects and API classes
Bug-29002-Add-Booking-objects-and-API-classes.patch (text/plain), 39.64 KB, created by
Martin Renvoize
on 2023-05-15 18:05:38 UTC
(
hide
)
Description:
Bug 29002: Add Booking objects and API classes
Filename:
MIME Type:
Creator:
Martin Renvoize
Created:
2023-05-15 18:05:38 UTC
Size:
39.64 KB
patch
obsolete
>From 4d885efe378e70fc211bf539d261b23ce23c26f7 Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@ptfs-europe.com> >Date: Thu, 16 Sep 2021 09:17:30 +0100 >Subject: [PATCH] Bug 29002: Add Booking objects and API classes > >--- > Koha/Biblio.pm | 107 +++++++++++ > Koha/Booking.pm | 212 +++++++++++++++++++++ > Koha/Bookings.pm | 59 ++++++ > Koha/Exceptions/Booking.pm | 15 ++ > Koha/Item.pm | 105 +++++++++++ > Koha/REST/V1/Biblios.pm | 34 ++++ > Koha/REST/V1/Bookings.pm | 165 +++++++++++++++++ > Koha/REST/V1/Items.pm | 34 ++++ > api/v1/swagger/definitions/booking.yaml | 45 +++++ > api/v1/swagger/parameters/booking.yaml | 6 + > api/v1/swagger/paths/biblios.yaml | 68 +++++++ > api/v1/swagger/paths/bookings.yaml | 235 ++++++++++++++++++++++++ > api/v1/swagger/paths/items.yaml | 54 ++++++ > api/v1/swagger/swagger.yaml | 46 +++-- > 14 files changed, 1170 insertions(+), 15 deletions(-) > create mode 100644 Koha/Booking.pm > create mode 100644 Koha/Bookings.pm > create mode 100644 Koha/Exceptions/Booking.pm > create mode 100644 Koha/REST/V1/Bookings.pm > create mode 100644 api/v1/swagger/definitions/booking.yaml > create mode 100644 api/v1/swagger/parameters/booking.yaml > create mode 100644 api/v1/swagger/paths/bookings.yaml > >diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm >index 50d60c8a69..0a4bf7d2ee 100644 >--- a/Koha/Biblio.pm >+++ b/Koha/Biblio.pm >@@ -36,6 +36,7 @@ use Koha::Biblio::Metadatas; > use Koha::Biblio::ItemGroups; > use Koha::Biblioitems; > use Koha::Cache::Memory::Lite; >+use Koha::Bookings; > use Koha::Checkouts; > use Koha::CirculationRules; > use Koha::Exceptions; >@@ -199,6 +200,98 @@ sub can_article_request { > return q{}; > } > >+=head3 check_booking >+ >+ my $bookable = >+ $biblio->check_booking( { start_date => $datetime, end_date => $datetime, [ booking_id => $booking_id ] } ); >+ >+Returns a boolean denoting whether the passed booking can be made without clashing. >+ >+Optionally, you may pass a booking id to exclude from the checks; This is helpful when you are updating an existing booking. >+ >+=cut >+ >+sub check_booking { >+ my ( $self, $params ) = @_; >+ >+ my $start_date = dt_from_string( $params->{start_date} ); >+ my $end_date = dt_from_string( $params->{end_date} ); >+ my $booking_id = $params->{booking_id}; >+ >+ my $bookable_items = $self->items; >+ my $total_bookable = $bookable_items->count; >+ >+ my $dtf = Koha::Database->new->schema->storage->datetime_parser; >+ my $existing_bookings = $self->bookings( >+ [ >+ start_date => { >+ '-between' => [ >+ $dtf->format_datetime($start_date), >+ $dtf->format_datetime($end_date) >+ ] >+ }, >+ end_date => { >+ '-between' => [ >+ $dtf->format_datetime($start_date), >+ $dtf->format_datetime($end_date) >+ ] >+ }, >+ { >+ start_date => { '<' => $dtf->format_datetime($start_date) }, >+ end_date => { '>' => $dtf->format_datetime($end_date) } >+ } >+ ] >+ ); >+ >+ my $booked_count = >+ defined($booking_id) >+ ? $existing_bookings->search( { booking_id => { '!=' => $booking_id } } ) >+ ->count >+ : $existing_bookings->count; >+ return ( ( $total_bookable - $booked_count ) > 0 ) ? 1 : 0; >+} >+ >+=head3 place_booking >+ >+ my $booking = $biblio->place_booking( >+ { >+ patron => $patron, >+ start_date => $datetime, >+ end_date => $datetime >+ } >+ ); >+ >+Add a booking for this item for the dates passed. >+ >+Returns the Koha::Booking object or throws an exception if the item cannot be booked for the given dates. >+ >+=cut >+ >+sub place_booking { >+ my ( $self, $params ) = @_; >+ >+ # check for mandatory params >+ my @mandatory = ( 'start_date', 'end_date', 'patron' ); >+ for my $param (@mandatory) { >+ unless ( defined( $params->{$param} ) ) { >+ Koha::Exceptions::MissingParameter->throw( >+ error => "The $param parameter is mandatory" ); >+ } >+ } >+ my $patron = $params->{patron}; >+ >+ # New booking object >+ my $booking = Koha::Booking->new( >+ { >+ start_date => $params->{start_date}, >+ end_date => $params->{end_date}, >+ borrowernumber => $patron->borrowernumber, >+ biblionumber => $self->biblionumber >+ } >+ )->store(); >+ return $booking; >+} >+ > =head3 can_be_transferred > > $biblio->can_be_transferred({ to => $to_library, from => $from_library }) >@@ -569,6 +662,20 @@ sub biblioitem { > return $self->{_biblioitem}; > } > >+=head3 bookings >+ >+ my $bookings = $item->bookings(); >+ >+Returns the bookings attached to this biblio. >+ >+=cut >+ >+sub bookings { >+ my ( $self, $params ) = @_; >+ my $bookings_rs = $self->_result->bookings->search($params); >+ return Koha::Bookings->_new_from_dbic( $bookings_rs ); >+} >+ > =head3 suggestions > > my $suggestions = $self->suggestions >diff --git a/Koha/Booking.pm b/Koha/Booking.pm >new file mode 100644 >index 0000000000..bb8ff26b30 >--- /dev/null >+++ b/Koha/Booking.pm >@@ -0,0 +1,212 @@ >+package Koha::Booking; >+ >+# Copyright PTFS Europe 2021 >+# >+# 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 Koha::Exceptions::Booking; >+use Koha::DateUtils qw( dt_from_string ); >+ >+use base qw(Koha::Object); >+ >+=head1 NAME >+ >+Koha::Booking - Koha Booking object class >+ >+=head1 API >+ >+=head2 Class methods >+ >+=head3 biblio >+ >+Returns the related Koha::Biblio object for this booking >+ >+=cut >+ >+sub biblio { >+ my ($self) = @_; >+ >+ my $biblio_rs = $self->_result->biblio; >+ return Koha::Biblio->_new_from_dbic($biblio_rs); >+} >+ >+=head3 patron >+ >+Returns the related Koha::Patron object for this booking >+ >+=cut >+ >+sub patron { >+ my ($self) = @_; >+ >+ my $patron_rs = $self->_result->patron; >+ return Koha::Patron->_new_from_dbic($patron_rs); >+} >+ >+=head3 item >+ >+Returns the related Koha::Item object for this Booking >+ >+=cut >+ >+sub item { >+ my ($self) = @_; >+ >+ my $item_rs = $self->_result->item; >+ return unless $item_rs; >+ return Koha::Item->_new_from_dbic($item_rs); >+} >+ >+=head3 store >+ >+Booking specific store method to catch booking clashes >+ >+=cut >+ >+sub store { >+ my ($self) = @_; >+ >+ $self->_result->result_source->schema->txn_do( >+ sub { >+ if ( $self->item_id ) { >+ Koha::Exceptions::Object::FKConstraint->throw( >+ broken_fk => 'item_id', >+ value => $self->item_id, >+ ) unless ( $self->item ); >+ >+ $self->biblio_id( $self->item->biblionumber ) >+ unless $self->biblio_id; >+ >+ Koha::Exceptions::Object::FKConstraint->throw() >+ unless ( $self->biblio_id == $self->item->biblionumber ); >+ } >+ >+ Koha::Exceptions::Object::FKConstraint->throw( >+ broken_fk => 'biblio_id', >+ value => $self->biblio_id, >+ ) unless ( $self->biblio ); >+ >+ # Throw exception for item level booking clash >+ Koha::Exceptions::Booking::Clash->throw() >+ if $self->item_id && !$self->item->check_booking( >+ { >+ start_date => $self->start_date, >+ end_date => $self->end_date, >+ booking_id => $self->in_storage ? $self->booking_id : undef >+ } >+ ); >+ >+ # Throw exception for biblio level booking clash >+ Koha::Exceptions::Booking::Clash->throw() >+ if !$self->biblio->check_booking( >+ { >+ start_date => $self->start_date, >+ end_date => $self->end_date, >+ booking_id => $self->in_storage ? $self->booking_id : undef >+ } >+ ); >+ >+ $self = $self->SUPER::store; >+ } >+ ); >+ >+ return $self; >+} >+ >+=head3 intersects >+ >+ my $intersects = $booking1->intersects($booking2); >+ >+Returns a boolean denoting whether booking1 interfers/overlaps/clashes with booking2. >+ >+=cut >+ >+sub intersects { >+ my ( $self, $comp ) = @_; >+ >+ # Start date of comparison booking is after end date of this booking. >+ return 0 >+ if ( >+ DateTime->compare( >+ dt_from_string( $comp->start_date ), >+ dt_from_string( $self->end_date ) >+ ) >= 0 >+ ); >+ >+ # End date of comparison booking is before start date of this booking. >+ return 0 >+ if ( >+ DateTime->compare( >+ dt_from_string( $comp->end_date ), >+ dt_from_string( $self->start_date ) >+ ) <= 0 >+ ); >+ >+ # Bookings must overlap >+ return 1; >+} >+ >+=head3 get_items_that_can_fill >+ >+ my $items = $bookings->get_items_that_can_fill(); >+ >+Return the list of items that can fulfill this booking. >+ >+Items that are not: >+ >+ in transit >+ lost >+ withdrawn >+ not for loan >+ not already booked >+ >+=cut >+ >+sub get_items_that_can_fill { >+ my ($self) = @_; >+ return; >+} >+ >+=head3 to_api_mapping >+ >+This method returns the mapping for representing a Koha::Booking object >+on the API. >+ >+=cut >+ >+sub to_api_mapping { >+ return {}; >+} >+ >+=head2 Internal methods >+ >+=head3 _type >+ >+=cut >+ >+sub _type { >+ return 'Booking'; >+} >+ >+=head1 AUTHORS >+ >+Martin Renvoize <martin.renvoize@ptfs-europe.com> >+ >+=cut >+ >+1; >diff --git a/Koha/Bookings.pm b/Koha/Bookings.pm >new file mode 100644 >index 0000000000..44bc032b02 >--- /dev/null >+++ b/Koha/Bookings.pm >@@ -0,0 +1,59 @@ >+package Koha::Bookings; >+ >+# Copyright PTFS Europe 2021 >+# >+# 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 Koha::Database; >+use Koha::Booking; >+ >+use base qw(Koha::Objects); >+ >+=head1 NAME >+ >+Koha::Bookings - Koha Booking object set class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 type >+ >+=cut >+ >+sub _type { >+ return 'Booking'; >+} >+ >+=head3 object_class >+ >+=cut >+ >+sub object_class { >+ return 'Koha::Booking'; >+} >+ >+=head1 AUTHOR >+ >+Martin Renvoize <martin.renvoize@ptfs-europe.com> >+ >+=cut >+ >+1; >diff --git a/Koha/Exceptions/Booking.pm b/Koha/Exceptions/Booking.pm >new file mode 100644 >index 0000000000..9ebae153cb >--- /dev/null >+++ b/Koha/Exceptions/Booking.pm >@@ -0,0 +1,15 @@ >+package Koha::Exceptions::Booking; >+ >+use Modern::Perl; >+ >+use Exception::Class ( >+ 'Koha::Exceptions::Booking' => { >+ description => "Something went wrong!" >+ }, >+ 'Koha::Exceptions::Booking::Clash' => { >+ isa => 'Koha::Exceptions::Booking', >+ description => "Adding or updateing the booking would result in a clash" >+ }, >+); >+ >+1; >diff --git a/Koha/Item.pm b/Koha/Item.pm >index ea2677a01f..27d1efc615 100644 >--- a/Koha/Item.pm >+++ b/Koha/Item.pm >@@ -484,6 +484,111 @@ sub holds { > return Koha::Holds->_new_from_dbic( $holds_rs ); > } > >+=head3 bookings >+ >+ my $bookings = $item->bookings(); >+ >+Returns the bookings attached to this item. >+ >+=cut >+ >+sub bookings { >+ my ( $self, $params ) = @_; >+ my $bookings_rs = $self->_result->bookings->search($params); >+ return Koha::Bookings->_new_from_dbic( $bookings_rs ); >+} >+ >+=head3 check_booking >+ >+ my $bookable = >+ $item->check_booking( { start_date => $datetime, end_date => $datetime, [ booking_id => $booking_id ] } ); >+ >+Returns a boolean denoting whether the passed booking can be made without clashing. >+ >+Optionally, you may pass a booking id to exclude from the checks; This is helpful when you are updating an existing booking. >+ >+=cut >+ >+sub check_booking { >+ my ($self, $params) = @_; >+ >+ my $start_date = dt_from_string( $params->{start_date} ); >+ my $end_date = dt_from_string( $params->{end_date} ); >+ my $booking_id = $params->{booking_id}; >+ >+ my $dtf = Koha::Database->new->schema->storage->datetime_parser; >+ my $existing_bookings = $self->bookings( >+ [ >+ start_date => { >+ '-between' => [ >+ $dtf->format_datetime($start_date), >+ $dtf->format_datetime($end_date) >+ ] >+ }, >+ end_date => { >+ '-between' => [ >+ $dtf->format_datetime($start_date), >+ $dtf->format_datetime($end_date) >+ ] >+ }, >+ { >+ start_date => { '<' => $dtf->format_datetime($start_date) }, >+ end_date => { '>' => $dtf->format_datetime($end_date) } >+ } >+ ] >+ ); >+ >+ my $bookings_count = >+ defined($booking_id) >+ ? $existing_bookings->search( { booking_id => { '!=' => $booking_id } } ) >+ ->count >+ : $existing_bookings->count; >+ >+ return $bookings_count ? 0 : 1; >+} >+ >+=head3 place_booking >+ >+ my $booking = $item->place_booking( >+ { >+ patron => $patron, >+ start_date => $datetime, >+ end_date => $datetime >+ } >+ ); >+ >+Add a booking for this item for the dates passed. >+ >+Returns the Koha::Booking object or throws an exception if the item cannot be booked for the given dates. >+ >+=cut >+ >+sub place_booking { >+ my ( $self, $params ) = @_; >+ >+ # check for mandatory params >+ my @mandatory = ( 'start_date', 'end_date', 'patron' ); >+ for my $param (@mandatory) { >+ unless ( defined( $params->{$param} ) ) { >+ Koha::Exceptions::MissingParameter->throw( >+ error => "The $param parameter is mandatory" ); >+ } >+ } >+ my $patron = $params->{patron}; >+ >+ # New booking object >+ my $booking = Koha::Booking->new( >+ { >+ start_date => $params->{start_date}, >+ end_date => $params->{end_date}, >+ borrowernumber => $patron->borrowernumber, >+ biblionumber => $self->biblionumber, >+ itemnumber => $self->itemnumber, >+ } >+ )->store(); >+ return $booking; >+} >+ > =head3 request_transfer > > my $transfer = $item->request_transfer( >diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm >index 6457d49d7a..9db9a3ae7c 100644 >--- a/Koha/REST/V1/Biblios.pm >+++ b/Koha/REST/V1/Biblios.pm >@@ -246,6 +246,40 @@ sub get_public { > }; > } > >+=head3 get_bookings >+ >+Controller function that handles retrieving biblio's bookings >+ >+=cut >+ >+sub get_bookings { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $biblio = Koha::Biblios->find( { biblionumber => $c->validation->param('biblio_id') }, { prefetch => ['bookings'] } ); >+ >+ unless ( $biblio ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => "Object not found." >+ } >+ ); >+ } >+ >+ return try { >+ >+ my $bookings_rs = $biblio->bookings; >+ my $bookings = $c->objects->search( $bookings_rs ); >+ return $c->render( >+ status => 200, >+ openapi => $bookings >+ ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ > =head3 get_items > > Controller function that handles retrieving biblio's items >diff --git a/Koha/REST/V1/Bookings.pm b/Koha/REST/V1/Bookings.pm >new file mode 100644 >index 0000000000..cc1ad4a97c >--- /dev/null >+++ b/Koha/REST/V1/Bookings.pm >@@ -0,0 +1,165 @@ >+package Koha::REST::V1::Bookings; >+ >+# 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 Mojo::Base 'Mojolicious::Controller'; >+ >+use Koha::Bookings; >+ >+use Try::Tiny qw( catch try ); >+ >+=head1 API >+ >+=head2 Methods >+ >+=head3 list >+ >+Controller function that handles retrieving a list of bookings >+ >+=cut >+ >+sub list { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ my $bookings_set = Koha::Bookings->new; >+ my $bookings = $c->objects->search($bookings_set); >+ return $c->render( status => 200, openapi => $bookings ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+ >+} >+ >+=head3 get >+ >+Controller function that handles retrieving a single booking >+ >+=cut >+ >+sub get { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ my $booking = >+ Koha::Bookings->find( $c->validation->param('booking_id') ); >+ unless ($booking) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Booking not found" } >+ ); >+ } >+ >+ return $c->render( status => 200, openapi => $booking->to_api ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ } >+} >+ >+=head3 add >+ >+Controller function that handles adding a new booking >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ my $booking = >+ Koha::Booking->new_from_api( $c->validation->param('body') ); >+ $booking->store; >+ $c->res->headers->location( >+ $c->req->url->to_string . '/' . $booking->booking_id ); >+ return $c->render( >+ status => 201, >+ openapi => $booking->to_api >+ ); >+ } >+ catch { >+ if ( blessed $_ and $_->isa('Koha::Exceptions::Booking::Clash') ) { >+ return $c->render( >+ status => 400, >+ openapi => { error => "Booking would conflict" } >+ ); >+ } >+ >+ return $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 update >+ >+Controller function that handles updating an existing booking >+ >+=cut >+ >+sub update { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $booking = Koha::Bookings->find( $c->validation->param('booking_id') ); >+ >+ if ( not defined $booking ) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Object not found" } >+ ); >+ } >+ >+ return try { >+ $booking->set_from_api( $c->validation->param('body') ); >+ $booking->store(); >+ return $c->render( status => 200, openapi => $booking->to_api ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 delete >+ >+Controller function that handles removing an existing booking >+ >+=cut >+ >+sub delete { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $booking = Koha::Bookings->find( $c->validation->param('booking_id') ); >+ if ( not defined $booking ) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Object not found" } >+ ); >+ } >+ >+ return try { >+ $booking->delete; >+ return $c->render( >+ status => 204, >+ openapi => q{} >+ ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+1; >diff --git a/Koha/REST/V1/Items.pm b/Koha/REST/V1/Items.pm >index 938ffcd659..157b6f7650 100644 >--- a/Koha/REST/V1/Items.pm >+++ b/Koha/REST/V1/Items.pm >@@ -174,6 +174,40 @@ sub delete { > }; > } > >+=head3 get_bookings >+ >+Controller function that handles retrieving item's bookings >+ >+=cut >+ >+sub get_bookings { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $item = Koha::Items->find( { itemnumber => $c->validation->param('item_id') }, { prefetch => ['bookings'] } ); >+ >+ unless ( $item ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => "Object not found." >+ } >+ ); >+ } >+ >+ return try { >+ >+ my $bookings_rs = $item->bookings; >+ my $bookings = $c->objects->search( $bookings_rs ); >+ return $c->render( >+ status => 200, >+ openapi => $bookings >+ ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ > =head3 pickup_locations > > Method that returns the possible pickup_locations for a given item >diff --git a/api/v1/swagger/definitions/booking.yaml b/api/v1/swagger/definitions/booking.yaml >new file mode 100644 >index 0000000000..23393a60ff >--- /dev/null >+++ b/api/v1/swagger/definitions/booking.yaml >@@ -0,0 +1,45 @@ >+--- >+additionalProperties: false >+properties: >+ biblio_id: >+ description: Internal identifier for the parent bibliographic record >+ type: integer >+ biblio: >+ description: Embedable biblio representation >+ type: object >+ booking_id: >+ description: Internal booking identifier >+ type: integer >+ end_date: >+ description: Start date and time of this booking >+ format: date-time >+ type: string >+ item_id: >+ description: Internal item identifier >+ type: >+ - integer >+ - "null" >+ item: >+ description: Embedable item representation >+ type: >+ - object >+ - "null" >+ patron_id: >+ description: Internal patron identifier >+ type: integer >+ patron: >+ description: Embedable patron representation >+ type: >+ - object >+ - "null" >+ start_date: >+ description: Start date and time of this booking >+ format: date-time >+ type: string >+required: >+ - biblio_id >+ - item_id >+ - patron_id >+ - start_date >+ - end_date >+type: object >diff --git a/api/v1/swagger/parameters/booking.yaml b/api/v1/swagger/parameters/booking.yaml >new file mode 100644 >index 0000000000..a4273fd880 >--- /dev/null >+++ b/api/v1/swagger/parameters/booking.yaml >@@ -0,0 +1,6 @@ >+booking_id_pp: >+ name: booking_id >+ in: path >+ description: Booking internal identifier >+ required: true >+ type: integer >diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml >index fa98f152a5..9ce749c470 100644 >--- a/api/v1/swagger/paths/biblios.yaml >+++ b/api/v1/swagger/paths/biblios.yaml >@@ -275,6 +275,74 @@ > x-koha-authorization: > permissions: > editcatalogue: edit_catalogue >+"/biblios/{biblio_id}/bookings": >+ get: >+ x-mojo-to: Biblios#get_bookings >+ operationId: getBiblioBookings >+ tags: >+ - bookings >+ summary: Get bookings for a biblio >+ parameters: >+ - $ref: "../swagger.yaml#/parameters/biblio_id_pp" >+ - $ref: "../swagger.yaml#/parameters/match" >+ - $ref: "../swagger.yaml#/parameters/order_by" >+ - $ref: "../swagger.yaml#/parameters/page" >+ - $ref: "../swagger.yaml#/parameters/per_page" >+ - $ref: "../swagger.yaml#/parameters/q_param" >+ - $ref: "../swagger.yaml#/parameters/q_body" >+ - $ref: "../swagger.yaml#/parameters/q_header" >+ - name: x-koha-embed >+ in: header >+ required: false >+ description: Embed list sent as a request header >+ type: array >+ items: >+ type: string >+ enum: >+ - item >+ - patron >+ collectionFormat: csv >+ consumes: >+ - application/json >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: A list of the bookings attached to the record >+ schema: >+ type: array >+ items: >+ $ref: ../swagger.yaml#/definitions/booking >+ "401": >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: Biblio not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "406": >+ description: Not acceptable >+ schema: >+ type: array >+ description: Accepted content-types >+ items: >+ type: string >+ "500": >+ description: Internal server error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ circulation: "1" > "/biblios/{biblio_id}/checkouts": > get: > x-mojo-to: Biblios#get_checkouts >diff --git a/api/v1/swagger/paths/bookings.yaml b/api/v1/swagger/paths/bookings.yaml >new file mode 100644 >index 0000000000..90903d9d9d >--- /dev/null >+++ b/api/v1/swagger/paths/bookings.yaml >@@ -0,0 +1,235 @@ >+--- >+/bookings: >+ get: >+ x-mojo-to: Bookings#list >+ operationId: listBookings >+ parameters: >+ - description: Case insensative search on booking biblio_id >+ in: query >+ name: biblio_id >+ required: false >+ type: string >+ - description: Case insensative search on booking item_id >+ in: query >+ name: item_id >+ required: false >+ type: string >+ - description: Case insensative search on booking patron_id >+ in: query >+ name: patron_id >+ required: false >+ type: string >+ - description: Case Insensative search on booking start_date >+ in: query >+ name: start_date >+ required: false >+ type: string >+ - description: Case Insensative search on booking end_date >+ in: query >+ name: end_date >+ required: false >+ type: string >+ - $ref: "../swagger.yaml#/parameters/match" >+ - $ref: "../swagger.yaml#/parameters/order_by" >+ - $ref: "../swagger.yaml#/parameters/page" >+ - $ref: "../swagger.yaml#/parameters/per_page" >+ - $ref: "../swagger.yaml#/parameters/q_param" >+ - $ref: "../swagger.yaml#/parameters/q_body" >+ - $ref: "../swagger.yaml#/parameters/q_header" >+ - name: x-koha-embed >+ in: header >+ required: false >+ description: Embed list sent as a request header >+ type: array >+ items: >+ type: string >+ enum: >+ - biblio >+ - item >+ - patron >+ collectionFormat: csv >+ produces: >+ - application/json >+ responses: >+ 200: >+ description: A list of bookings >+ schema: >+ items: >+ $ref: ../swagger.yaml#/definitions/booking >+ type: array >+ 403: >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 500: >+ description: Internal error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ summary: List bookings >+ tags: >+ - bookings >+ x-koha-authorization: >+ permissions: >+ catalogue: 1 >+ post: >+ operationId: addBooking >+ parameters: >+ - description: A JSON object containing informations about the new booking >+ in: body >+ name: body >+ required: true >+ schema: >+ $ref: ../swagger.yaml#/definitions/booking >+ produces: >+ - application/json >+ responses: >+ 201: >+ description: Booking added >+ schema: >+ $ref: ../swagger.yaml#/definitions/booking >+ 400: >+ description: Client error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 401: >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 403: >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 500: >+ description: Internal error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ summary: Add booking >+ tags: >+ - bookings >+ x-koha-authorization: >+ permissions: >+ parameters: manage_bookings >+ x-mojo-to: Bookings#add >+'/bookings/{booking_id}': >+ delete: >+ operationId: deleteBooking >+ parameters: >+ - $ref: "../swagger.yaml#/parameters/booking_id_pp" >+ produces: >+ - application/json >+ responses: >+ 204: >+ description: Booking deleted >+ 401: >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 403: >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 404: >+ description: Booking not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 500: >+ description: Internal error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ summary: Delete booking >+ tags: >+ - bookings >+ x-koha-authorization: >+ permissions: >+ parameters: manage_bookings >+ x-mojo-to: Bookings#delete >+ get: >+ operationId: getBooking >+ parameters: >+ - $ref: "../swagger.yaml#/parameters/booking_id_pp" >+ produces: >+ - application/json >+ responses: >+ 200: >+ description: A booking >+ schema: >+ $ref: ../swagger.yaml#/definitions/booking >+ 404: >+ description: Booking not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 500: >+ description: Internal error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ summary: Get booking >+ tags: >+ - bookings >+ x-koha-authorization: >+ permissions: >+ catalogue: 1 >+ x-mojo-to: Bookings#get >+ put: >+ operationId: updateBooking >+ parameters: >+ - $ref: "../swagger.yaml#/parameters/booking_id_pp" >+ - description: A booking object >+ in: body >+ name: body >+ required: true >+ schema: >+ $ref: ../swagger.yaml#/definitions/booking >+ produces: >+ - application/json >+ responses: >+ 200: >+ description: A booking >+ schema: >+ $ref: ../swagger.yaml#/definitions/booking >+ 400: >+ description: Client error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 401: >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 403: >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 404: >+ description: Booking not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 500: >+ description: Internal error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ summary: Update booking >+ tags: >+ - bookings >+ x-koha-authorization: >+ permissions: >+ parameters: manage_bookings >+ x-mojo-to: Bookings#update >diff --git a/api/v1/swagger/paths/items.yaml b/api/v1/swagger/paths/items.yaml >index ac8c313a14..f5ebfc8630 100644 >--- a/api/v1/swagger/paths/items.yaml >+++ b/api/v1/swagger/paths/items.yaml >@@ -333,6 +333,60 @@ > x-koha-authorization: > permissions: > catalogue: 1 >+/items/{item_id}/bookings: >+ get: >+ x-mojo-to: Items#bookings >+ operationId: getItemBookings >+ summary: Get existing bookings for an item >+ tags: >+ - items >+ parameters: >+ - $ref: "../swagger.yaml#/parameters/item_id_pp" >+ - $ref: "../swagger.yaml#/parameters/match" >+ - $ref: "../swagger.yaml#/parameters/order_by" >+ - $ref: "../swagger.yaml#/parameters/page" >+ - $ref: "../swagger.yaml#/parameters/per_page" >+ - $ref: "../swagger.yaml#/parameters/q_param" >+ - $ref: "../swagger.yaml#/parameters/q_body" >+ - $ref: "../swagger.yaml#/parameters/q_header" >+ consumes: >+ - application/json >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: Item bookings >+ schema: >+ type: array >+ items: >+ $ref: ../swagger.yaml#/definitions/booking >+ "400": >+ description: Missing or wrong parameters >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "401": >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: Item not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: Internal server error >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ circulation: 1 > "/items/{item_id}/pickup_locations": > get: > x-mojo-to: Items#pickup_locations >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index 23c59b96a1..7ffc2b5ba6 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -13,11 +13,13 @@ definitions: > authorised_value_category: > $ref: ./definitions/authorised_value_category.yaml > identity_provider: >- "$ref": ./definitions/identity_provider.yaml >+ $ref: ./definitions/identity_provider.yaml > identity_provider_domain: >- "$ref": ./definitions/identity_provider_domain.yaml >+ $ref: ./definitions/identity_provider_domain.yaml > basket: > $ref: ./definitions/basket.yaml >+ booking: >+ $ref: ./definitions/booking.yaml > bundle_link: > $ref: ./definitions/bundle_link.yaml > cashup: >@@ -110,13 +112,13 @@ definitions: > $ref: ./definitions/vendor.yaml > paths: > /acquisitions/baskets/managers: >- $ref: paths/acquisitions_baskets.yaml#/~1acquisitions~1baskets~1managers >+ $ref: ./paths/acquisitions_baskets.yaml#/~1acquisitions~1baskets~1managers > /acquisitions/funds: > $ref: ./paths/acquisitions_funds.yaml#/~1acquisitions~1funds > /acquisitions/funds/owners: >- $ref: paths/acquisitions_funds.yaml#/~1acquisitions~1funds~1owners >+ $ref: ./paths/acquisitions_funds.yaml#/~1acquisitions~1funds~1owners > /acquisitions/funds/users: >- $ref: paths/acquisitions_funds.yaml#/~1acquisitions~1funds~1users >+ $ref: ./paths/acquisitions_funds.yaml#/~1acquisitions~1funds~1users > /acquisitions/orders: > $ref: ./paths/acquisitions_orders.yaml#/~1acquisitions~1orders > "/acquisitions/orders/{order_id}": >@@ -129,6 +131,10 @@ paths: > $ref: ./paths/advancededitormacros.yaml#/~1advanced_editor~1macros > /advanced_editor/macros/shared: > $ref: ./paths/advancededitormacros.yaml#/~1advanced_editor~1macros~1shared >+ /bookings: >+ $ref: ./paths/bookings.yaml#/~1bookings >+ "/bookings/{booking_id}": >+ $ref: ./paths/bookings.yaml#/~1bookings~1{booking_id} > /search_filters: > $ref: ./paths/search_filters.yaml#/~1search_filters > "/search_filters/{search_filter_id}": >@@ -140,33 +146,35 @@ paths: > "/article_requests/{article_request_id}": > $ref: "./paths/article_requests.yaml#/~1article_requests~1{article_request_id}" > /auth/otp/token_delivery: >- $ref: paths/auth.yaml#/~1auth~1otp~1token_delivery >+ $ref: "./paths/auth.yaml#/~1auth~1otp~1token_delivery" > "/auth/password/validation": > $ref: "./paths/auth.yaml#/~1auth~1password~1validation" > /auth/two-factor/registration: >- $ref: paths/auth.yaml#/~1auth~1two-factor~1registration >+ $ref: ./paths/auth.yaml#/~1auth~1two-factor~1registration > /auth/two-factor/registration/verification: >- $ref: paths/auth.yaml#/~1auth~1two-factor~1registration~1verification >+ $ref: ./paths/auth.yaml#/~1auth~1two-factor~1registration~1verification > /auth/identity_providers: >- $ref: paths/auth.yaml#/~1auth~1identity_providers >+ $ref: ./paths/auth.yaml#/~1auth~1identity_providers > "/auth/identity_providers/{identity_provider_id}": >- $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id} >+ $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id} > "/auth/identity_providers/{identity_provider_id}/domains": >- $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains >+ $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains > "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}": >- $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id} >+ $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id} > /authorised_value_categories: >- $ref: paths/authorised_value_categories.yaml#/~1authorised_value_categories >+ $ref: ./paths/authorised_value_categories.yaml#/~1authorised_value_categories > "/authorised_value_categories/{authorised_value_category_name}/authorised_values": > $ref: "./paths/authorised_values.yaml#/~1authorised_value_categories~1{authorised_value_category_name}~1authorised_values" > "/authorities": > $ref: paths/authorities.yaml#/~1authorities > "/authorities/{authority_id}": >- $ref: paths/authorities.yaml#/~1authorities~1{authority_id} >+ $ref: "./paths/authorities.yaml#/~1authorities~1{authority_id}" > "/biblios": > $ref: "./paths/biblios.yaml#/~1biblios" > "/biblios/{biblio_id}": > $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}" >+ "/biblios/{biblio_id}/bookings": >+ $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1bookings" > "/biblios/{biblio_id}/checkouts": > $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1checkouts" > "/biblios/{biblio_id}/items": >@@ -267,6 +275,8 @@ paths: > $ref: ./paths/items.yaml#/~1items > "/items/{item_id}": > $ref: "./paths/items.yaml#/~1items~1{item_id}" >+ "/items/{item_id}/bookings": >+ $ref: "./paths/items.yaml#/~1items~1{item_id}~1bookings" > "/items/{item_id}/bundled_items": > $ref: ./paths/items.yaml#/~1items~1{item_id}~1bundled_items > "/items/{item_id}/bundled_items/{bundled_item_id}": >@@ -346,7 +356,7 @@ paths: > "/suggestions/{suggestion_id}": > $ref: "./paths/suggestions.yaml#/~1suggestions~1{suggestion_id}" > /suggestions/managers: >- $ref: paths/suggestions.yaml#/~1suggestions~1managers >+ $ref: "./paths/suggestions.yaml#/~1suggestions~1managers" > "/tickets": > $ref: "./paths/tickets.yaml#/~1tickets" > "/tickets/{ticket_id}": >@@ -396,6 +406,12 @@ parameters: > in: header > required: false > type: string >+ booking_id_pp: >+ description: Booking identifier >+ in: path >+ name: booking_id >+ required: true >+ type: integer > framework_id_header: > description: Framework id. Use when content type is not application/json > name: x-framework-id >-- >2.40.1
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 29002
:
125456
|
125457
|
125458
|
125459
|
151209
|
151211
|
151213
|
151216
|
151217
|
151218
|
158357
|
158358
|
160831