Nick Clemens
02326ebf24
This patch adjusts the code that uses GetOpenIssue to use/find a Koha::Checkout object instead To test: 1 - Add a course to course reserves 2 - Create an item with barcode TESTKOC 3 - Add the item to a course 4 - Checkout the item 5 - View course details on stff and opac and confirm item shows as checked out and due date displays 6 - prove t/db_dependent/Circulation/issue.t t/db_dependent/Circulation.t t/db_dependent/CourseReserves.t 7 - Browse to Circulation->Upload offline circulation 8 - Upload a file to return the item: https://wiki.koha-community.org/wiki/Koha_offline_circulation_file_format 9 - Confirm item is returned Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
1089 lines
29 KiB
Perl
1089 lines
29 KiB
Perl
package C4::CourseReserves;
|
|
|
|
# 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 List::MoreUtils qw( any );
|
|
|
|
use C4::Context;
|
|
|
|
use Koha::Courses;
|
|
use Koha::Course::Instructors;
|
|
use Koha::Course::Items;
|
|
use Koha::Course::Reserves;
|
|
use Koha::Checkouts;
|
|
|
|
use vars qw(@FIELDS);
|
|
our (@ISA, @EXPORT_OK);
|
|
BEGIN {
|
|
require Exporter;
|
|
@ISA = qw(Exporter);
|
|
@EXPORT_OK = qw(
|
|
GetCourse
|
|
ModCourse
|
|
GetCourses
|
|
DelCourse
|
|
|
|
GetCourseInstructors
|
|
ModCourseInstructors
|
|
|
|
GetCourseItem
|
|
ModCourseItem
|
|
|
|
GetCourseReserve
|
|
ModCourseReserve
|
|
GetCourseReserves
|
|
DelCourseReserve
|
|
|
|
SearchCourses
|
|
|
|
GetItemCourseReservesInfo
|
|
);
|
|
|
|
@FIELDS = ( 'itype', 'ccode', 'homebranch', 'holdingbranch', 'location' );
|
|
}
|
|
|
|
=head1 NAME
|
|
|
|
C4::CourseReserves - Koha course reserves module
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use C4::CourseReserves;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This module deals with course reserves.
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
=head2 GetCourse
|
|
|
|
$course = GetCourse( $course_id );
|
|
|
|
=cut
|
|
|
|
sub GetCourse {
|
|
my ($course_id) = @_;
|
|
|
|
my $course = Koha::Courses->find( $course_id );
|
|
return unless $course;
|
|
$course = $course->unblessed;
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $query = "
|
|
SELECT b.* FROM course_instructors ci
|
|
LEFT JOIN borrowers b ON ( ci.borrowernumber = b.borrowernumber )
|
|
WHERE course_id = ?
|
|
";
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute($course_id);
|
|
$course->{'instructors'} = $sth->fetchall_arrayref( {} );
|
|
|
|
return $course;
|
|
}
|
|
|
|
=head2 ModCourse
|
|
|
|
ModCourse( [ course_id => $id ] [, course_name => $course_name ] [etc...] );
|
|
|
|
=cut
|
|
|
|
sub ModCourse {
|
|
my (%params) = @_;
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
|
|
my $course_id;
|
|
if ( defined $params{'course_id'} ) {
|
|
$course_id = $params{'course_id'};
|
|
delete $params{'course_id'};
|
|
}
|
|
|
|
my @query_keys;
|
|
my @query_values;
|
|
|
|
my $query;
|
|
|
|
$query .= ($course_id) ? ' UPDATE ' : ' INSERT ';
|
|
$query .= ' courses SET ';
|
|
|
|
foreach my $key ( keys %params ) {
|
|
push( @query_keys, "$key=?" );
|
|
push( @query_values, $params{$key} );
|
|
}
|
|
$query .= join( ',', @query_keys );
|
|
|
|
if ($course_id) {
|
|
$query .= " WHERE course_id = ?";
|
|
push( @query_values, $course_id );
|
|
}
|
|
|
|
$dbh->do( $query, undef, @query_values );
|
|
|
|
$course_id = $course_id
|
|
|| $dbh->last_insert_id( undef, undef, 'courses', 'course_id' );
|
|
|
|
EnableOrDisableCourseItems(
|
|
course_id => $course_id,
|
|
enabled => $params{'enabled'}
|
|
);
|
|
|
|
return $course_id;
|
|
}
|
|
|
|
=head2 GetCourses
|
|
|
|
@courses = GetCourses( [ fieldname => $value ] [, fieldname2 => $value2 ] [etc...] );
|
|
|
|
=cut
|
|
|
|
sub GetCourses {
|
|
my (%params) = @_;
|
|
|
|
my @query_keys;
|
|
my @query_values;
|
|
|
|
my $query = "
|
|
SELECT c.course_id, c.department, c.course_number, c.section, c.course_name, c.term, c.staff_note, c.public_note, c.students_count, c.enabled, c.timestamp
|
|
FROM courses c
|
|
LEFT JOIN course_reserves ON course_reserves.course_id = c.course_id
|
|
LEFT JOIN course_items ON course_items.ci_id = course_reserves.ci_id
|
|
";
|
|
|
|
if ( keys %params ) {
|
|
|
|
$query .= " WHERE ";
|
|
|
|
foreach my $key ( keys %params ) {
|
|
push( @query_keys, " $key LIKE ? " );
|
|
push( @query_values, $params{$key} );
|
|
}
|
|
|
|
$query .= join( ' AND ', @query_keys );
|
|
}
|
|
|
|
$query .= " GROUP BY c.course_id, c.department, c.course_number, c.section, c.course_name, c.term, c.staff_note, c.public_note, c.students_count, c.enabled, c.timestamp ";
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute(@query_values);
|
|
|
|
my $courses = $sth->fetchall_arrayref( {} );
|
|
|
|
foreach my $c (@$courses) {
|
|
$c->{'instructors'} = GetCourseInstructors( $c->{'course_id'} );
|
|
}
|
|
|
|
return $courses;
|
|
}
|
|
|
|
=head2 DelCourse
|
|
|
|
DelCourse( $course_id );
|
|
|
|
=cut
|
|
|
|
sub DelCourse {
|
|
my ($course_id) = @_;
|
|
|
|
my $course_reserves = GetCourseReserves( course_id => $course_id );
|
|
|
|
foreach my $res (@$course_reserves) {
|
|
DelCourseReserve( cr_id => $res->{'cr_id'} );
|
|
}
|
|
|
|
my $query = "
|
|
DELETE FROM course_instructors
|
|
WHERE course_id = ?
|
|
";
|
|
C4::Context->dbh->do( $query, undef, $course_id );
|
|
|
|
$query = "
|
|
DELETE FROM courses
|
|
WHERE course_id = ?
|
|
";
|
|
C4::Context->dbh->do( $query, undef, $course_id );
|
|
}
|
|
|
|
=head2 EnableOrDisableCourseItems
|
|
|
|
EnableOrDisableCourseItems( course_id => $course_id, enabled => $enabled );
|
|
|
|
For each item on reserve for this course,
|
|
if the course item has no active course reserves,
|
|
swap the fields for the item to make it 'normal'
|
|
again.
|
|
|
|
enabled => 'yes' to enable course items
|
|
enabled => 'no' to disable course items
|
|
|
|
=cut
|
|
|
|
sub EnableOrDisableCourseItems {
|
|
my (%params) = @_;
|
|
|
|
my $course_id = $params{'course_id'};
|
|
my $enabled = $params{'enabled'} || 0;
|
|
|
|
my $lookfor = ( $enabled eq 'yes' ) ? 'no' : 'yes';
|
|
|
|
return unless ( $course_id && $enabled );
|
|
return unless ( $enabled eq 'yes' || $enabled eq 'no' );
|
|
|
|
my $course_reserves = GetCourseReserves( course_id => $course_id );
|
|
|
|
if ( $enabled eq 'yes' ) {
|
|
foreach my $course_reserve (@$course_reserves) {
|
|
if (CountCourseReservesForItem(
|
|
ci_id => $course_reserve->{'ci_id'},
|
|
enabled => 'yes'
|
|
)
|
|
) {
|
|
EnableOrDisableCourseItem(
|
|
ci_id => $course_reserve->{'ci_id'},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if ( $enabled eq 'no' ) {
|
|
foreach my $course_reserve (@$course_reserves) {
|
|
unless (
|
|
CountCourseReservesForItem(
|
|
ci_id => $course_reserve->{'ci_id'},
|
|
enabled => 'yes'
|
|
)
|
|
) {
|
|
EnableOrDisableCourseItem(
|
|
ci_id => $course_reserve->{'ci_id'},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
=head2 EnableOrDisableCourseItem
|
|
|
|
EnableOrDisableCourseItem( ci_id => $ci_id );
|
|
|
|
=cut
|
|
|
|
sub EnableOrDisableCourseItem {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
|
|
return unless ( $ci_id );
|
|
|
|
my $course_item = GetCourseItem( ci_id => $ci_id );
|
|
|
|
my $info = $course_item->{itemnumber} ? GetItemCourseReservesInfo( itemnumber => $course_item->{itemnumber} ) : GetItemCourseReservesInfo( biblionumber => $course_item->{biblionumber} );
|
|
|
|
my $enabled = any { $_->{course}->{enabled} eq 'yes' } @$info;
|
|
$enabled = $enabled ? 'yes' : 'no';
|
|
|
|
## We don't want to 'enable' an already enabled item,
|
|
## or disable and already disabled item,
|
|
## as that would cause the fields to swap
|
|
if ( $course_item->{'enabled'} ne $enabled ) {
|
|
_SwapAllFields($ci_id, $enabled );
|
|
|
|
my $query = "
|
|
UPDATE course_items
|
|
SET enabled = ?
|
|
WHERE ci_id = ?
|
|
";
|
|
|
|
C4::Context->dbh->do( $query, undef, $enabled, $ci_id );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
=head2 GetCourseInstructors
|
|
|
|
@$borrowers = GetCourseInstructors( $course_id );
|
|
|
|
=cut
|
|
|
|
sub GetCourseInstructors {
|
|
my ($course_id) = @_;
|
|
|
|
my $query = "
|
|
SELECT * FROM borrowers
|
|
RIGHT JOIN course_instructors ON ( course_instructors.borrowernumber = borrowers.borrowernumber )
|
|
WHERE course_instructors.course_id = ?
|
|
";
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute($course_id);
|
|
|
|
return $sth->fetchall_arrayref( {} );
|
|
}
|
|
|
|
=head2 ModCourseInstructors
|
|
|
|
ModCourseInstructors( mode => $mode, course_id => $course_id, [ cardnumbers => $cardnumbers ] OR [ borrowernumbers => $borrowernumbers );
|
|
|
|
$mode can be 'replace', 'add', or 'delete'
|
|
|
|
$cardnumbers and $borrowernumbers are both references to arrays
|
|
|
|
Use either cardnumbers or borrowernumber, but not both.
|
|
|
|
=cut
|
|
|
|
sub ModCourseInstructors {
|
|
my (%params) = @_;
|
|
|
|
my $course_id = $params{'course_id'};
|
|
my $mode = $params{'mode'};
|
|
my $cardnumbers = $params{'cardnumbers'};
|
|
my $borrowernumbers = $params{'borrowernumbers'};
|
|
|
|
return unless ($course_id);
|
|
return
|
|
unless ( $mode eq 'replace'
|
|
|| $mode eq 'add'
|
|
|| $mode eq 'delete' );
|
|
return unless ( $cardnumbers || $borrowernumbers );
|
|
return if ( $cardnumbers && $borrowernumbers );
|
|
|
|
my ( @cardnumbers, @borrowernumbers );
|
|
@cardnumbers = @$cardnumbers if ( ref($cardnumbers) eq 'ARRAY' );
|
|
@borrowernumbers = @$borrowernumbers
|
|
if ( ref($borrowernumbers) eq 'ARRAY' );
|
|
|
|
my $field = (@cardnumbers) ? 'cardnumber' : 'borrowernumber';
|
|
my @fields = (@cardnumbers) ? @cardnumbers : @borrowernumbers;
|
|
my $placeholders = join( ',', ('?') x scalar @fields );
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
|
|
$dbh->do( "DELETE FROM course_instructors WHERE course_id = ?", undef, $course_id )
|
|
if ( $mode eq 'replace' );
|
|
|
|
my $query;
|
|
|
|
if ( $mode eq 'add' || $mode eq 'replace' ) {
|
|
$query = "
|
|
INSERT INTO course_instructors ( course_id, borrowernumber )
|
|
SELECT ?, borrowernumber
|
|
FROM borrowers
|
|
WHERE $field IN ( $placeholders )
|
|
";
|
|
} else {
|
|
$query = "
|
|
DELETE FROM course_instructors
|
|
WHERE course_id = ?
|
|
AND borrowernumber IN (
|
|
SELECT borrowernumber FROM borrowers WHERE $field IN ( $placeholders )
|
|
)
|
|
";
|
|
}
|
|
|
|
my $sth = $dbh->prepare($query);
|
|
|
|
$sth->execute( $course_id, @fields ) if (@fields);
|
|
}
|
|
|
|
=head2 GetCourseItem {
|
|
|
|
Given one of biblionumber, itenumber, or ci_id, returns hashref of the course_items values
|
|
|
|
$course_item = GetCourseItem( itemnumber => $itemnumber [, ci_id => $ci_id ] );
|
|
$course_item = GetCourseItem( biblionumber => $biblionumber [, ci_id => $ci_id ]);
|
|
$course_item = GetCourseItem( ci_id => $ci_id );
|
|
|
|
=cut
|
|
|
|
sub GetCourseItem {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
my $itemnumber = $params{'itemnumber'};
|
|
my $biblionumber = $params{'biblionumber'};
|
|
|
|
return unless ( $itemnumber xor $biblionumber xor $ci_id );
|
|
|
|
my ( $field, $value );
|
|
if ( $itemnumber ) {
|
|
$field = 'itemnumber';
|
|
$value = $itemnumber;
|
|
} elsif ( $biblionumber ) {
|
|
$field = 'biblionumber';
|
|
$value = $biblionumber;
|
|
} else {
|
|
$field = 'ci_id';
|
|
$value = $ci_id;
|
|
}
|
|
|
|
my $query = "SELECT * FROM course_items WHERE $field = ?";
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute($value);
|
|
|
|
my $course_item = $sth->fetchrow_hashref();
|
|
|
|
if ($course_item) {
|
|
$query = "SELECT * FROM course_reserves WHERE ci_id = ?";
|
|
$sth = $dbh->prepare($query);
|
|
$sth->execute( $course_item->{'ci_id'} );
|
|
my $course_reserves = $sth->fetchall_arrayref( {} );
|
|
|
|
$course_item->{'course_reserves'} = $course_reserves
|
|
if ($course_reserves);
|
|
}
|
|
return $course_item;
|
|
}
|
|
|
|
=head2 ModCourseItem {
|
|
|
|
ModCourseItem( %params );
|
|
|
|
Creates or modifies an existing course item. Must be passed either an itemnumber or biblionumber parameter
|
|
|
|
=cut
|
|
|
|
sub ModCourseItem {
|
|
my (%params) = @_;
|
|
|
|
my $itemnumber = $params{'itemnumber'};
|
|
my $biblionumber = $params{'biblionumber'};
|
|
|
|
return unless ($itemnumber xor $biblionumber);
|
|
|
|
my $course_item = $itemnumber ? GetCourseItem( itemnumber => $itemnumber ) : GetCourseItem( biblionumber => $biblionumber );
|
|
|
|
if ( $itemnumber and !$biblionumber ) {
|
|
$biblionumber = Koha::Items->find( $itemnumber )->biblionumber;
|
|
$params{biblionumber} = $biblionumber;
|
|
}
|
|
|
|
my $ci_id;
|
|
|
|
if ($course_item) {
|
|
$ci_id = $course_item->{'ci_id'};
|
|
|
|
_UpdateCourseItem(
|
|
ci_id => $ci_id,
|
|
course_item => $course_item,
|
|
%params
|
|
);
|
|
} else {
|
|
$ci_id = _AddCourseItem(%params);
|
|
}
|
|
|
|
return $ci_id;
|
|
|
|
}
|
|
|
|
=head2 _AddCourseItem
|
|
|
|
my $ci_id = _AddCourseItem( %params );
|
|
|
|
=cut
|
|
|
|
sub _AddCourseItem {
|
|
my (%params) = @_;
|
|
|
|
$params{homebranch} ||= undef; # Can't be empty string, FK constraint
|
|
$params{holdingbranch} ||= undef; # Can't be empty string, FK constraint
|
|
|
|
my %data = map { $_ => $params{$_} } @FIELDS;
|
|
my %enabled = map { $_ . "_enabled" => $params{ $_ . "_enabled" } } @FIELDS;
|
|
|
|
my $ci = Koha::Course::Item->new(
|
|
{
|
|
itemnumber => $params{itemnumber},
|
|
biblionumber => $params{biblionumber},
|
|
%data,
|
|
%enabled,
|
|
}
|
|
)->store();
|
|
|
|
return $ci->id;
|
|
}
|
|
|
|
=head2 _UpdateCourseItem
|
|
|
|
_UpdateCourseItem( %params );
|
|
|
|
=cut
|
|
|
|
sub _UpdateCourseItem {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
my $course_item = $params{'course_item'};
|
|
|
|
$params{homebranch} ||= undef; # Can't be empty string, FK constraint
|
|
$params{holdingbranch} ||= undef; # Can't be empty string, FK constraint
|
|
|
|
return unless ( $ci_id || $course_item );
|
|
|
|
$course_item = Koha::Course::Items->find( $ci_id || $course_item->{ci_id} );
|
|
|
|
my %data = map { $_ => $params{$_} } @FIELDS;
|
|
my %enabled = map { $_ . "_enabled" => $params{ $_ . "_enabled" } } @FIELDS;
|
|
|
|
if ( $course_item->itemnumber ) {
|
|
# biblio-level course items don't store any of these fields
|
|
my $item = Koha::Items->find( $course_item->itemnumber );
|
|
|
|
# Handle updates to changed fields for a course item, both adding and removing
|
|
if ( $course_item->is_enabled ) {
|
|
my $item_fields = {};
|
|
|
|
for my $field ( @FIELDS ) {
|
|
|
|
my $field_enabled = $field . '_enabled';
|
|
my $field_storage = $field . '_storage';
|
|
|
|
# Find newly enabled field and add item value to storage
|
|
if ( $params{$field_enabled} && !$course_item->$field_enabled ) {
|
|
$enabled{$field_storage} = $item->$field;
|
|
$item_fields->{$field} = $params{$field};
|
|
}
|
|
# Find newly disabled field and copy the storage value to the item, unset storage value
|
|
elsif ( !$params{$field_enabled} && $course_item->$field_enabled ) {
|
|
$item_fields->{$field} = $course_item->$field_storage;
|
|
$enabled{$field_storage} = undef;
|
|
}
|
|
# The field was already enabled, copy the incoming value to the item.
|
|
# The "original" ( when not on course reserve ) value is already in the storage field
|
|
elsif ( $course_item->$field_enabled) {
|
|
$item_fields->{$field} = $params{$field};
|
|
}
|
|
}
|
|
|
|
$item->set( $item_fields )->store
|
|
if keys %$item_fields;
|
|
}
|
|
}
|
|
|
|
$course_item->update( { %data, %enabled } );
|
|
|
|
}
|
|
|
|
=head2 _RevertFields
|
|
|
|
_RevertFields( ci_id => $ci_id, fields => \@fields_to_revert );
|
|
|
|
Copies fields from course item storage back to the actual item
|
|
|
|
=cut
|
|
|
|
sub _RevertFields {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
|
|
return unless $ci_id;
|
|
|
|
my $course_item = Koha::Course::Items->find( $ci_id );
|
|
|
|
my $item_fields = {};
|
|
$item_fields->{itype} = $course_item->itype_storage if $course_item->itype_enabled;
|
|
$item_fields->{ccode} = $course_item->ccode_storage if $course_item->ccode_enabled;
|
|
$item_fields->{location} = $course_item->location_storage if $course_item->location_enabled;
|
|
$item_fields->{homebranch} = $course_item->homebranch_storage if $course_item->homebranch_enabled;
|
|
$item_fields->{holdingbranch} = $course_item->holdingbranch_storage if $course_item->holdingbranch_enabled;
|
|
|
|
Koha::Items->find( $course_item->itemnumber )
|
|
->set( $item_fields )
|
|
->store
|
|
if keys %$item_fields;
|
|
|
|
$course_item->itype_storage(undef);
|
|
$course_item->ccode_storage(undef);
|
|
$course_item->location_storage(undef);
|
|
$course_item->homebranch_storage(undef);
|
|
$course_item->holdingbranch_storage(undef);
|
|
$course_item->store();
|
|
}
|
|
|
|
=head2 _SwapAllFields
|
|
|
|
_SwapAllFields( $ci_id );
|
|
|
|
=cut
|
|
|
|
sub _SwapAllFields {
|
|
my ( $ci_id, $enabled ) = @_;
|
|
|
|
my $course_item = Koha::Course::Items->find( $ci_id );
|
|
my $item = Koha::Items->find( $course_item->itemnumber );
|
|
|
|
if ( $enabled eq 'yes' ) { # Copy item fields to course item storage, course item fields to item
|
|
$course_item->itype_storage( $item->effective_itemtype ) if $course_item->itype_enabled;
|
|
$course_item->ccode_storage( $item->ccode ) if $course_item->ccode_enabled;
|
|
$course_item->location_storage( $item->location ) if $course_item->location_enabled;
|
|
$course_item->homebranch_storage( $item->homebranch ) if $course_item->homebranch_enabled;
|
|
$course_item->holdingbranch_storage( $item->holdingbranch ) if $course_item->holdingbranch_enabled;
|
|
$course_item->store();
|
|
|
|
my $item_fields = {};
|
|
$item_fields->{itype} = $course_item->itype if $course_item->itype_enabled;
|
|
$item_fields->{ccode} = $course_item->ccode if $course_item->ccode_enabled;
|
|
$item_fields->{location} = $course_item->location if $course_item->location_enabled;
|
|
$item_fields->{homebranch} = $course_item->homebranch if $course_item->homebranch_enabled;
|
|
$item_fields->{holdingbranch} = $course_item->holdingbranch if $course_item->holdingbranch_enabled;
|
|
|
|
Koha::Items->find( $course_item->itemnumber )
|
|
->set( $item_fields )
|
|
->store
|
|
if keys %$item_fields;
|
|
|
|
} else { # Copy course item storage to item
|
|
my $item_fields = {};
|
|
$item_fields->{itype} = $course_item->itype_storage if $course_item->itype_enabled;
|
|
$item_fields->{ccode} = $course_item->ccode_storage if $course_item->ccode_enabled;
|
|
$item_fields->{location} = $course_item->location_storage if $course_item->location_enabled;
|
|
$item_fields->{homebranch} = $course_item->homebranch_storage if $course_item->homebranch_enabled;
|
|
$item_fields->{holdingbranch} = $course_item->holdingbranch_storage if $course_item->holdingbranch_enabled;
|
|
|
|
Koha::Items->find( $course_item->itemnumber )
|
|
->set( $item_fields )
|
|
->store
|
|
if keys %$item_fields;
|
|
|
|
$course_item->itype_storage(undef);
|
|
$course_item->ccode_storage(undef);
|
|
$course_item->location_storage(undef);
|
|
$course_item->homebranch_storage(undef);
|
|
$course_item->holdingbranch_storage(undef);
|
|
$course_item->store();
|
|
}
|
|
}
|
|
|
|
=head2 GetCourseItems {
|
|
|
|
$course_items = GetCourseItems(
|
|
[course_id => $course_id]
|
|
[, itemnumber => $itemnumber ]
|
|
);
|
|
|
|
=cut
|
|
|
|
sub GetCourseItems {
|
|
my (%params) = @_;
|
|
|
|
my $course_id = $params{'course_id'};
|
|
my $itemnumber = $params{'itemnumber'};
|
|
|
|
return unless ($course_id);
|
|
|
|
my @query_keys;
|
|
my @query_values;
|
|
|
|
my $query = "SELECT * FROM course_items";
|
|
|
|
if ( keys %params ) {
|
|
|
|
$query .= " WHERE ";
|
|
|
|
foreach my $key ( keys %params ) {
|
|
push( @query_keys, " $key LIKE ? " );
|
|
push( @query_values, $params{$key} );
|
|
}
|
|
|
|
$query .= join( ' AND ', @query_keys );
|
|
}
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute(@query_values);
|
|
|
|
return $sth->fetchall_arrayref( {} );
|
|
}
|
|
|
|
=head2 DelCourseItem {
|
|
|
|
DelCourseItem( ci_id => $cr_id );
|
|
|
|
=cut
|
|
|
|
sub DelCourseItem {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
|
|
return unless ($ci_id);
|
|
|
|
my $course_item = Koha::Course::Items->find( $ci_id );
|
|
return unless $course_item;
|
|
|
|
_RevertFields( ci_id => $ci_id ) if $course_item->enabled eq 'yes';
|
|
|
|
my $query = "
|
|
DELETE FROM course_items
|
|
WHERE ci_id = ?
|
|
";
|
|
C4::Context->dbh->do( $query, undef, $ci_id );
|
|
}
|
|
|
|
=head2 GetCourseReserve {
|
|
|
|
$course_item = GetCourseReserve( %params );
|
|
|
|
=cut
|
|
|
|
sub GetCourseReserve {
|
|
my (%params) = @_;
|
|
|
|
my $cr_id = $params{'cr_id'};
|
|
my $course_id = $params{'course_id'};
|
|
my $ci_id = $params{'ci_id'};
|
|
|
|
return unless ( $cr_id || ( $course_id && $ci_id ) );
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth;
|
|
|
|
if ($cr_id) {
|
|
my $query = "
|
|
SELECT * FROM course_reserves
|
|
WHERE cr_id = ?
|
|
";
|
|
$sth = $dbh->prepare($query);
|
|
$sth->execute($cr_id);
|
|
} else {
|
|
my $query = "
|
|
SELECT * FROM course_reserves
|
|
WHERE course_id = ? AND ci_id = ?
|
|
";
|
|
$sth = $dbh->prepare($query);
|
|
$sth->execute( $course_id, $ci_id );
|
|
}
|
|
|
|
my $course_reserve = $sth->fetchrow_hashref();
|
|
return $course_reserve;
|
|
}
|
|
|
|
=head2 ModCourseReserve
|
|
|
|
$id = ModCourseReserve( %params );
|
|
|
|
=cut
|
|
|
|
sub ModCourseReserve {
|
|
my (%params) = @_;
|
|
|
|
my $course_id = $params{'course_id'};
|
|
my $ci_id = $params{'ci_id'};
|
|
my $staff_note = $params{'staff_note'};
|
|
my $public_note = $params{'public_note'};
|
|
|
|
return unless ( $course_id && $ci_id );
|
|
|
|
my $course_reserve = GetCourseReserve( course_id => $course_id, ci_id => $ci_id );
|
|
my $cr_id;
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
|
|
if ($course_reserve) {
|
|
$cr_id = $course_reserve->{'cr_id'};
|
|
|
|
my $query = "
|
|
UPDATE course_reserves
|
|
SET staff_note = ?, public_note = ?
|
|
WHERE cr_id = ?
|
|
";
|
|
$dbh->do( $query, undef, $staff_note, $public_note, $cr_id );
|
|
} else {
|
|
my $query = "
|
|
INSERT INTO course_reserves SET
|
|
course_id = ?,
|
|
ci_id = ?,
|
|
staff_note = ?,
|
|
public_note = ?
|
|
";
|
|
$dbh->do( $query, undef, $course_id, $ci_id, $staff_note, $public_note );
|
|
$cr_id = $dbh->last_insert_id( undef, undef, 'course_reserves', 'cr_id' );
|
|
}
|
|
|
|
EnableOrDisableCourseItem(
|
|
ci_id => $params{'ci_id'},
|
|
);
|
|
|
|
return $cr_id;
|
|
}
|
|
|
|
=head2 GetCourseReserves {
|
|
|
|
$course_reserves = GetCourseReserves( %params );
|
|
|
|
Required:
|
|
course_id OR ci_id
|
|
Optional:
|
|
include_items => 1,
|
|
include_count => 1,
|
|
include_courses => 1,
|
|
|
|
=cut
|
|
|
|
sub GetCourseReserves {
|
|
my (%params) = @_;
|
|
|
|
my $course_id = $params{'course_id'};
|
|
my $ci_id = $params{'ci_id'};
|
|
my $include_items = $params{'include_items'};
|
|
my $include_count = $params{'include_count'};
|
|
my $include_courses = $params{'include_courses'};
|
|
|
|
return unless ( $course_id || $ci_id );
|
|
|
|
my $field = ($course_id) ? 'course_id' : 'ci_id';
|
|
my $value = ($course_id) ? $course_id : $ci_id;
|
|
|
|
my $query = "
|
|
SELECT cr.*, ci.itemnumber, ci.biblionumber
|
|
FROM course_reserves cr, course_items ci
|
|
WHERE cr.$field = ?
|
|
AND cr.ci_id = ci.ci_id
|
|
";
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute($value);
|
|
|
|
my $course_reserves = $sth->fetchall_arrayref( {} );
|
|
|
|
if ($include_items) {
|
|
foreach my $cr (@$course_reserves) {
|
|
my $item = Koha::Items->find( $cr->{itemnumber}, { prefetch => ['biblio','biblioitem'] });
|
|
my $biblio = $cr->{itemnumber} ? $item->biblio : Koha::Biblios->find( $cr->{biblionumber}, { prefetch => ['biblioitem'] });
|
|
my $biblioitem = $biblio->biblioitem;
|
|
$cr->{'course_item'} = GetCourseItem( ci_id => $cr->{'ci_id'} );
|
|
$cr->{'item'} = $item;
|
|
$cr->{'biblio'} = $biblio;
|
|
$cr->{'biblioitem'} = $biblioitem;
|
|
$cr->{'issue'} = Koha::Checkouts->find({ itemnumber => $cr->{'itemnumber'} });
|
|
}
|
|
}
|
|
|
|
if ($include_count) {
|
|
foreach my $cr (@$course_reserves) {
|
|
$cr->{'reserves_count'} = CountCourseReservesForItem( ci_id => $cr->{'ci_id'} );
|
|
}
|
|
}
|
|
|
|
if ($include_courses) {
|
|
foreach my $cr (@$course_reserves) {
|
|
$cr->{'courses'} = $cr->{itemnumber} ? GetCourses( itemnumber => $cr->{'itemnumber'} ) : GetCourses( biblionumber => $cr->{biblionumber} );
|
|
}
|
|
}
|
|
|
|
return $course_reserves;
|
|
}
|
|
|
|
=head2 DelCourseReserve {
|
|
|
|
DelCourseReserve( cr_id => $cr_id );
|
|
|
|
=cut
|
|
|
|
sub DelCourseReserve {
|
|
my (%params) = @_;
|
|
|
|
my $cr_id = $params{'cr_id'};
|
|
|
|
return unless ($cr_id);
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
|
|
my $course_reserve = GetCourseReserve( cr_id => $cr_id );
|
|
|
|
my $query = "
|
|
DELETE FROM course_reserves
|
|
WHERE cr_id = ?
|
|
";
|
|
$dbh->do( $query, undef, $cr_id );
|
|
|
|
## If there are no other course reserves for this item
|
|
## delete the course_item as well
|
|
unless ( CountCourseReservesForItem( ci_id => $course_reserve->{'ci_id'} ) ) {
|
|
DelCourseItem( ci_id => $course_reserve->{'ci_id'} );
|
|
}
|
|
|
|
}
|
|
|
|
=head2 GetItemCourseReservesInfo
|
|
|
|
my $arrayref = GetItemCourseReservesInfo( itemnumber => $itemnumber );
|
|
my $arrayref = GetItemCourseReservesInfo( biblionumber => $biblionumber );
|
|
|
|
For a given itemnumber or biblionumber, returns an arrayref of reserves hashrefs,
|
|
with a course hashref under the key 'course'
|
|
|
|
=cut
|
|
|
|
sub GetItemCourseReservesInfo {
|
|
my (%params) = @_;
|
|
|
|
my $itemnumber = $params{'itemnumber'};
|
|
my $biblionumber = $params{'biblionumber'};
|
|
|
|
return unless ($itemnumber xor $biblionumber);
|
|
|
|
my $course_item = $itemnumber ? GetCourseItem( itemnumber => $itemnumber ) : GetCourseItem( biblionumber => $biblionumber );
|
|
|
|
return unless ( keys %$course_item );
|
|
|
|
my $course_reserves = GetCourseReserves( ci_id => $course_item->{'ci_id'} );
|
|
|
|
foreach my $cr (@$course_reserves) {
|
|
$cr->{'course'} = GetCourse( $cr->{'course_id'} );
|
|
}
|
|
|
|
return $course_reserves;
|
|
}
|
|
|
|
=head2 CountCourseReservesForItem
|
|
|
|
$bool = CountCourseReservesForItem( %params );
|
|
|
|
ci_id - course_item id
|
|
OR
|
|
itemnumber - course_item itemnumber
|
|
OR
|
|
biblionumber - course_item biblionumber
|
|
|
|
enabled = 'yes' or 'no'
|
|
Optional, if not supplied, counts reserves
|
|
for both enabled and disabled courses
|
|
|
|
=cut
|
|
|
|
sub CountCourseReservesForItem {
|
|
my (%params) = @_;
|
|
|
|
my $ci_id = $params{'ci_id'};
|
|
my $itemnumber = $params{'itemnumber'};
|
|
my $enabled = $params{'enabled'};
|
|
my $biblionumber = $params{'biblionumber'};
|
|
|
|
return unless ( $ci_id xor $itemnumber xor $biblionumber );
|
|
|
|
my $course_item = GetCourseItem( ci_id => $ci_id ) || GetCourseItem( itemnumber => $itemnumber ) || GetCourseItem( biblionumber => $biblionumber );
|
|
|
|
my @params = ( $course_item->{'ci_id'} );
|
|
push( @params, $enabled ) if ($enabled);
|
|
|
|
my $query = "
|
|
SELECT COUNT(*) AS count
|
|
FROM course_reserves cr
|
|
LEFT JOIN courses c ON ( c.course_id = cr.course_id )
|
|
WHERE ci_id = ?
|
|
";
|
|
$query .= "AND c.enabled = ?" if ($enabled);
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute(@params);
|
|
|
|
my $row = $sth->fetchrow_hashref();
|
|
|
|
return $row->{'count'};
|
|
}
|
|
|
|
=head2 SearchCourses
|
|
|
|
my $courses = SearchCourses( term => $search_term, enabled => 'yes' );
|
|
|
|
=cut
|
|
|
|
sub SearchCourses {
|
|
my (%params) = @_;
|
|
|
|
my $term = $params{'term'};
|
|
|
|
my $enabled = $params{'enabled'} || '%';
|
|
|
|
my @params;
|
|
my $query = "
|
|
SELECT c.course_id, c.department, c.course_number, c.section, c.course_name, c.term, c.staff_note, c.public_note, c.students_count, c.enabled, c.timestamp
|
|
FROM courses c
|
|
LEFT JOIN course_instructors ci
|
|
ON ( c.course_id = ci.course_id )
|
|
LEFT JOIN borrowers b
|
|
ON ( ci.borrowernumber = b.borrowernumber )
|
|
LEFT JOIN authorised_values av
|
|
ON ( c.department = av.authorised_value )
|
|
WHERE
|
|
( av.category = 'DEPARTMENT' OR av.category = 'TERM' )
|
|
AND
|
|
(
|
|
department LIKE ? OR
|
|
course_number LIKE ? OR
|
|
section LIKE ? OR
|
|
course_name LIKE ? OR
|
|
term LIKE ? OR
|
|
public_note LIKE ? OR
|
|
CONCAT(surname,' ',firstname) LIKE ? OR
|
|
CONCAT(firstname,' ',surname) LIKE ? OR
|
|
lib LIKE ? OR
|
|
lib_opac LIKE ?
|
|
)
|
|
AND
|
|
c.enabled LIKE ?
|
|
GROUP BY c.course_id, c.department, c.course_number, c.section, c.course_name, c.term, c.staff_note, c.public_note, c.students_count, c.enabled, c.timestamp
|
|
";
|
|
|
|
$term //= '';
|
|
$term = "%$term%";
|
|
@params = ($term) x 10;
|
|
|
|
$query .= " ORDER BY department, course_number, section, term, course_name ";
|
|
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare($query);
|
|
|
|
$sth->execute( @params, $enabled );
|
|
|
|
my $courses = $sth->fetchall_arrayref( {} );
|
|
|
|
foreach my $c (@$courses) {
|
|
$c->{'instructors'} = GetCourseInstructors( $c->{'course_id'} );
|
|
}
|
|
|
|
return $courses;
|
|
}
|
|
|
|
sub whoami { ( caller(1) )[3] }
|
|
sub whowasi { ( caller(2) )[3] }
|
|
|
|
sub stringify_params {
|
|
my (%params) = @_;
|
|
|
|
my $string = "\n";
|
|
|
|
foreach my $key ( keys %params ) {
|
|
$string .= " $key => " . $params{$key} . "\n";
|
|
}
|
|
|
|
return "( $string )";
|
|
}
|
|
|
|
1;
|
|
|
|
=head1 AUTHOR
|
|
|
|
Kyle M Hall <kyle@bywatersolutions.com>
|
|
|
|
=cut
|