package C4::Items;
# Copyright 2007 LibLime, Inc.
+# Parts Copyright Biblibre 2010
#
# This file is part of Koha.
#
# 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., 59 Temple Place,
-# Suite 330, Boston, MA 02111-1307 USA
+# 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 strict;
+#use warnings; FIXME - Bug 2505
+use Carp;
use C4::Context;
use C4::Koha;
use C4::Biblio;
use C4::Branch;
require C4::Reserves;
use C4::Charset;
+use C4::Acquisition;
use vars qw($VERSION @ISA @EXPORT);
AddItem
AddItemBatchFromMarc
ModItemFromMarc
+ Item2Marc
ModItem
ModDateLastSeen
ModItemTransfer
GetItemsInfo
get_itemnumbers_of
GetItemnumberFromBarcode
+ GetBarcodeFromItemnumber
+
+ DelItemCheck
+ MoveItemFromBiblio
+ GetLatestAcquisitions
+ CartToShelf
);
}
=head2 GetItem
-=over 4
-
-$item = GetItem($itemnumber,$barcode,$serial);
-
-=back
+ $item = GetItem($itemnumber,$barcode,$serial);
Return item information, for a given itemnumber or barcode.
The return value is a hashref mapping item column
my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?");
$ssth->execute($data->{'itemnumber'}) ;
($data->{'serialseq'} , $data->{'publisheddate'}) = $ssth->fetchrow_array();
- warn $data->{'serialseq'} , $data->{'publisheddate'};
- }
+ }
+ #if we don't have an items.itype, use biblioitems.itemtype.
+ if( ! $data->{'itype'} ) {
+ my $sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?");
+ $sth->execute($data->{'biblionumber'});
+ ($data->{'itype'}) = $sth->fetchrow_array;
+ }
return $data;
} # sub GetItem
-=head2 AddItemFromMarc
+=head2 CartToShelf
-=over 4
+ CartToShelf($itemnumber);
-my ($biblionumber, $biblioitemnumber, $itemnumber)
- = AddItemFromMarc($source_item_marc, $biblionumber);
+Set the current shelving location of the item record
+to its stored permanent shelving location. This is
+primarily used to indicate when an item whose current
+location is a special processing ('PROC') or shelving cart
+('CART') location is back in the stacks.
-=back
+=cut
+
+sub CartToShelf {
+ my ( $itemnumber ) = @_;
+
+ unless ( $itemnumber ) {
+ croak "FAILED CartToShelf() - no itemnumber supplied";
+ }
+
+ my $item = GetItem($itemnumber);
+ $item->{location} = $item->{permanent_location};
+ ModItem($item, undef, $itemnumber);
+}
+
+=head2 AddItemFromMarc
+
+ my ($biblionumber, $biblioitemnumber, $itemnumber)
+ = AddItemFromMarc($source_item_marc, $biblionumber);
Given a MARC::Record object containing an embedded item
record and a biblionumber, create a new item record.
# parse item hash from MARC
my $frameworkcode = GetFrameworkCode( $biblionumber );
- my $item = &TransformMarcToKoha( $dbh, $source_item_marc, $frameworkcode );
- my $unlinked_item_subfields = _get_unlinked_item_subfields($source_item_marc, $frameworkcode);
+ my ($itemtag,$itemsubfield)=GetMarcFromKohaField("items.itemnumber",$frameworkcode);
+
+ my $localitemmarc=MARC::Record->new;
+ $localitemmarc->append_fields($source_item_marc->field($itemtag));
+ my $item = &TransformMarcToKoha( $dbh, $localitemmarc, $frameworkcode ,'items');
+ my $unlinked_item_subfields = _get_unlinked_item_subfields($localitemmarc, $frameworkcode);
return AddItem($item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields);
}
=head2 AddItem
-=over 4
-
-my ($biblionumber, $biblioitemnumber, $itemnumber)
- = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields]);
-
-=back
+ my ($biblionumber, $biblioitemnumber, $itemnumber)
+ = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields]);
Given a hash containing item column names as keys,
create a new Koha item record.
_set_derived_columns_for_add($item);
$item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields);
# FIXME - checks here
+ unless ( $item->{itype} ) { # default to biblioitem.itemtype if no itype
+ my $itype_sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?");
+ $itype_sth->execute( $item->{'biblionumber'} );
+ ( $item->{'itype'} ) = $itype_sth->fetchrow_array;
+ }
+
my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} );
$item->{'itemnumber'} = $itemnumber;
my $new_item_marc = _marc_from_item_hash($item, $frameworkcode, $unlinked_item_subfields);
_add_item_field_to_biblio($new_item_marc, $item->{'biblionumber'}, $frameworkcode );
- logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$itemnumber,"item")
- if C4::Context->preference("CataloguingLog");
+ logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
return ($item->{biblionumber}, $item->{biblioitemnumber}, $itemnumber);
}
=head2 AddItemBatchFromMarc
-=over 4
-
-($itemnumber_ref, $error_ref) = AddItemBatchFromMarc($record, $biblionumber, $biblioitemnumber, $frameworkcode);
-
-=back
+ ($itemnumber_ref, $error_ref) = AddItemBatchFromMarc($record,
+ $biblionumber, $biblioitemnumber, $frameworkcode);
Efficiently create item records from a MARC biblio record with
embedded item fields. This routine is suitable for batch jobs.
errors encountered during the processing. Each entry in the errors
list is a hashref containing the following keys:
-=over 2
+=over
=item item_sequence
push @itemnumbers, $itemnumber; # FIXME not checking error
$item->{'itemnumber'} = $itemnumber;
- &logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$itemnumber,"item")
- if C4::Context->preference("CataloguingLog");
+ logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
my $new_item_marc = _marc_from_item_hash($item, $frameworkcode, $unlinked_item_subfields);
$item_field->replace_with($new_item_marc->field($itemtag));
=head2 ModItemFromMarc
-=over 4
-
-ModItemFromMarc($item_marc, $biblionumber, $itemnumber);
-
-=back
+ ModItemFromMarc($item_marc, $biblionumber, $itemnumber);
This function updates an item record based on a supplied
C<MARC::Record> object containing an embedded item field.
This API is meant for the use of C<additem.pl>; for
other purposes, C<ModItem> should be used.
+This function uses the hash %default_values_for_mod_from_marc,
+which contains default values for item fields to
+apply when modifying an item. This is needed beccause
+if an item field's value is cleared, TransformMarcToKoha
+does not include the column in the
+hash that's passed to ModItem, which without
+use of this hash makes it impossible to clear
+an item field's value. See bug 2466.
+
+Note that only columns that can be directly
+changed from the cataloging and serials
+item editors are included in this hash.
+
=cut
+my %default_values_for_mod_from_marc = (
+ barcode => undef,
+ booksellerid => undef,
+ ccode => undef,
+ 'items.cn_source' => undef,
+ copynumber => undef,
+ damaged => 0,
+# dateaccessioned => undef,
+ enumchron => undef,
+ holdingbranch => undef,
+ homebranch => undef,
+ itemcallnumber => undef,
+ itemlost => 0,
+ itemnotes => undef,
+ itype => undef,
+ location => undef,
+ materials => undef,
+ notforloan => 0,
+ paidfor => undef,
+ price => undef,
+ replacementprice => undef,
+ replacementpricedate => undef,
+ restricted => undef,
+ stack => undef,
+ stocknumber => undef,
+ uri => undef,
+ wthdrawn => 0,
+);
+
sub ModItemFromMarc {
my $item_marc = shift;
my $biblionumber = shift;
my $itemnumber = shift;
- my $dbh = C4::Context->dbh;
- my $frameworkcode = GetFrameworkCode( $biblionumber );
- my $item = &TransformMarcToKoha( $dbh, $item_marc, $frameworkcode );
- my $unlinked_item_subfields = _get_unlinked_item_subfields($item_marc, $frameworkcode);
-
+ my $dbh = C4::Context->dbh;
+ my $frameworkcode = GetFrameworkCode($biblionumber);
+ my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
+
+ my $localitemmarc = MARC::Record->new;
+ $localitemmarc->append_fields( $item_marc->field($itemtag) );
+ my $item = &TransformMarcToKoha( $dbh, $localitemmarc, $frameworkcode, 'items' );
+ foreach my $item_field ( keys %default_values_for_mod_from_marc ) {
+ $item->{$item_field} = $default_values_for_mod_from_marc{$item_field} unless (exists $item->{$item_field});
+ }
+ my $unlinked_item_subfields = _get_unlinked_item_subfields( $localitemmarc, $frameworkcode );
+
return ModItem($item, $biblionumber, $itemnumber, $dbh, $frameworkcode, $unlinked_item_subfields);
}
=head2 ModItem
-=over 4
-
-ModItem({ column => $newvalue }, $biblionumber, $itemnumber[, $original_item_marc]);
-
-=back
+ ModItem({ column => $newvalue }, $biblionumber,
+ $itemnumber[, $original_item_marc]);
Change one or more columns in an item record and update
the MARC representation of the item.
or die "FAILED _marc_from_item_hash($whole_item, $frameworkcode)";
_replace_item_field_in_biblio($new_item_marc, $biblionumber, $itemnumber, $frameworkcode);
- (C4::Context->userenv eq '0') and die "userenv is '0', not hashref"; # logaction line would crash anyway
($new_item_marc eq '0') and die "$new_item_marc is '0', not hashref"; # logaction line would crash anyway
- logaction(C4::Context->userenv->{'number'},"CATALOGUING","MODIFY",$itemnumber,$new_item_marc->as_formatted)
- if C4::Context->preference("CataloguingLog");
+ logaction("CATALOGUING", "MODIFY", $itemnumber, $new_item_marc->as_formatted) if C4::Context->preference("CataloguingLog");
}
=head2 ModItemTransfer
-=over 4
-
-ModItemTransfer($itenumber, $frombranch, $tobranch);
-
-=back
+ ModItemTransfer($itenumber, $frombranch, $tobranch);
Marks an item as being transferred from one branch
to another.
=head2 ModDateLastSeen
-=over 4
-
-ModDateLastSeen($itemnum);
-
-=back
+ ModDateLastSeen($itemnum);
Mark item as seen. Is called when an item is issued, returned or manually marked during inventory/stocktaking.
C<$itemnum> is the item number
=head2 DelItem
-=over 4
-
-DelItem($biblionumber, $itemnumber);
-
-=back
+ DelItem($dbh, $biblionumber, $itemnumber);
Exported function (core API) for deleting an item record in Koha.
}
}
&ModBiblioMarc( $record, $biblionumber, $frameworkcode );
- &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$itemnumber,"item")
- if C4::Context->preference("CataloguingLog");
+ logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
}
=head2 CheckItemPreSave
-=over 4
-
my $item_ref = TransformMarcToKoha($marc, 'items');
# do stuff
my %errors = CheckItemPreSave($item_ref);
print "item is OK";
}
-=back
-
Given a hashref containing item fields, determine if it can be
inserted or updated in the database. Specifically, checks for
database integrity issues, and returns a hash containing any
=head2 GetItemStatus
-=over 4
-
-$itemstatushash = GetItemStatus($fwkcode);
-
-=back
+ $itemstatushash = GetItemStatus($fwkcode);
Returns a list of valid values for the
C<items.notforloan> field.
=head3 in PERL SCRIPT
-=over 4
-
-my $itemstatushash = getitemstatus;
-my @itemstatusloop;
-foreach my $thisstatus (keys %$itemstatushash) {
- my %row =(value => $thisstatus,
- statusname => $itemstatushash->{$thisstatus}->{'statusname'},
- );
- push @itemstatusloop, \%row;
-}
-$template->param(statusloop=>\@itemstatusloop);
-
-=back
+ my $itemstatushash = getitemstatus;
+ my @itemstatusloop;
+ foreach my $thisstatus (keys %$itemstatushash) {
+ my %row =(value => $thisstatus,
+ statusname => $itemstatushash->{$thisstatus}->{'statusname'},
+ );
+ push @itemstatusloop, \%row;
+ }
+ $template->param(statusloop=>\@itemstatusloop);
=head3 in TEMPLATE
-=over 4
-
-<select name="statusloop">
- <option value="">Default</option>
-<!-- TMPL_LOOP name="statusloop" -->
- <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="statusname" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-
-=back
+ <select name="statusloop">
+ <option value="">Default</option>
+ <!-- TMPL_LOOP name="statusloop" -->
+ <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="statusname" --></option>
+ <!-- /TMPL_LOOP -->
+ </select>
=cut
while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
$itemstatus{$authorisedvalue} = $lib;
}
- $authvalsth->finish;
return \%itemstatus;
exit 1;
}
#No authvalue list
# build default
}
- $sth->finish;
}
#No authvalue list
=head2 GetItemLocation
-=over 4
-
-$itemlochash = GetItemLocation($fwk);
-
-=back
+ $itemlochash = GetItemLocation($fwk);
Returns a list of valid values for the
C<items.location> field.
=head3 in PERL SCRIPT
-=over 4
-
-my $itemlochash = getitemlocation;
-my @itemlocloop;
-foreach my $thisloc (keys %$itemlochash) {
- my $selected = 1 if $thisbranch eq $branch;
- my %row =(locval => $thisloc,
- selected => $selected,
- locname => $itemlochash->{$thisloc},
- );
- push @itemlocloop, \%row;
-}
-$template->param(itemlocationloop => \@itemlocloop);
-
-=back
+ my $itemlochash = getitemlocation;
+ my @itemlocloop;
+ foreach my $thisloc (keys %$itemlochash) {
+ my $selected = 1 if $thisbranch eq $branch;
+ my %row =(locval => $thisloc,
+ selected => $selected,
+ locname => $itemlochash->{$thisloc},
+ );
+ push @itemlocloop, \%row;
+ }
+ $template->param(itemlocationloop => \@itemlocloop);
=head3 in TEMPLATE
-=over 4
-
-<select name="location">
- <option value="">Default</option>
-<!-- TMPL_LOOP name="itemlocationloop" -->
- <option value="<!-- TMPL_VAR name="locval" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="locname" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-
-=back
+ <select name="location">
+ <option value="">Default</option>
+ <!-- TMPL_LOOP name="itemlocationloop" -->
+ <option value="<!-- TMPL_VAR name="locval" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="locname" --></option>
+ <!-- /TMPL_LOOP -->
+ </select>
=cut
while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
$itemlocation{$authorisedvalue} = $lib;
}
- $authvalsth->finish;
return \%itemlocation;
exit 1;
}
#No authvalue list
# build default
}
- $sth->finish;
}
#No authvalue list
=head2 GetLostItems
-=over 4
+ $items = GetLostItems( $where, $orderby );
-$items = GetLostItems($where,$orderby);
-
-=back
-
-This function get the items lost into C<$items>.
+This function gets a list of lost items.
=over 2
=item input:
+
C<$where> is a hashref. it containts a field of the items table as key
-and the value to match as value.
-C<$orderby> is a field of the items table.
+and the value to match as value. For example:
+
+{ barcode => 'abc123',
+ homebranch => 'CPL', }
+
+C<$orderby> is a field of the items table by which the resultset
+should be orderd.
=item return:
-C<$items> is a reference to an array full of hasref which keys are items' table column.
+
+C<$items> is a reference to an array full of hashrefs with columns
+from the "items" table as keys.
=item usage in the perl script:
-my %where;
-$where{barcode} = 0001548;
-my $items = GetLostItems( \%where, "homebranch" );
-$template->param(itemsloop => $items);
+ my $where = { barcode => '0001548' };
+ my $items = GetLostItems( $where, "homebranch" );
+ $template->param( itemsloop => $items );
=back
my $query = "
SELECT *
FROM items
- WHERE itemlost IS NOT NULL
- AND itemlost <> 0
+ LEFT JOIN biblio ON (items.biblionumber = biblio.biblionumber)
+ LEFT JOIN biblioitems ON (items.biblionumber = biblioitems.biblionumber)
+ LEFT JOIN authorised_values ON (items.itemlost = authorised_values.authorised_value)
+ WHERE
+ authorised_values.category = 'LOST'
+ AND itemlost IS NOT NULL
+ AND itemlost <> 0
";
+ my @query_parameters;
foreach my $key (keys %$where) {
- $query .= " AND " . $key . " LIKE '%" . $where->{$key} . "%'";
+ $query .= " AND $key LIKE ?";
+ push @query_parameters, "%$where->{$key}%";
+ }
+ my @ordervalues = qw/title author homebranch itype barcode price replacementprice lib datelastseen location/;
+
+ if ( defined $orderby && grep($orderby, @ordervalues)) {
+ $query .= ' ORDER BY '.$orderby;
}
- $query .= " ORDER BY ".$orderby if defined $orderby;
my $sth = $dbh->prepare($query);
- $sth->execute;
- my @items;
+ $sth->execute( @query_parameters );
+ my $items = [];
while ( my $row = $sth->fetchrow_hashref ){
- push @items, $row;
+ push @$items, $row;
}
- return \@items;
+ return $items;
}
=head2 GetItemsForInventory
-=over 4
-
-$itemlist = GetItemsForInventory($minlocation,$maxlocation,$datelastseen,$offset,$size)
-
-=back
+ $itemlist = GetItemsForInventory($minlocation, $maxlocation,
+ $location, $itemtype $datelastseen, $branch,
+ $offset, $size, $statushash);
Retrieve a list of title/authors/barcode/callnumber, for biblio inventory.
-The sub returns a list of hashes, containing itemnumber, author, title, barcode & item callnumber.
-It is ordered by callnumber,title.
+The sub returns a reference to a list of hashes, each containing
+itemnumber, author, title, barcode, item callnumber, and date last
+seen. It is ordered by callnumber then title.
-The minlocation & maxlocation parameters are used to specify a range of item callnumbers
+The required minlocation & maxlocation parameters are used to specify a range of item callnumbers
the datelastseen can be used to specify that you want to see items not seen since a past date only.
offset & size can be used to retrieve only a part of the whole listing (defaut behaviour)
+$statushash requires a hashref that has the authorized values fieldname (intems.notforloan, etc...) as keys, and an arrayref of statuscodes we are searching for as values.
=cut
sub GetItemsForInventory {
- my ( $minlocation, $maxlocation,$location, $itemtype, $datelastseen, $branch, $offset, $size ) = @_;
+ my ( $minlocation, $maxlocation,$location, $itemtype, $ignoreissued, $datelastseen, $branchcode, $branch, $offset, $size, $statushash ) = @_;
my $dbh = C4::Context->dbh;
- my $sth;
+ my ( @bind_params, @where_strings );
+
+ my $query = <<'END_SQL';
+SELECT items.itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, datelastseen
+FROM items
+ LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
+ LEFT JOIN biblioitems on items.biblionumber = biblioitems.biblionumber
+END_SQL
+ if ($statushash){
+ for my $authvfield (keys %$statushash){
+ if ( scalar @{$statushash->{$authvfield}} > 0 ){
+ my $joinedvals = join ',', @{$statushash->{$authvfield}};
+ push @where_strings, "$authvfield in (" . $joinedvals . ")";
+ }
+ }
+ }
+
+ if ($minlocation) {
+ push @where_strings, 'itemcallnumber >= ?';
+ push @bind_params, $minlocation;
+ }
+
+ if ($maxlocation) {
+ push @where_strings, 'itemcallnumber <= ?';
+ push @bind_params, $maxlocation;
+ }
+
if ($datelastseen) {
- $datelastseen=format_date_in_iso($datelastseen);
- my $query =
- "SELECT itemnumber,barcode,itemcallnumber,title,author,biblio.biblionumber,datelastseen
- FROM items
- LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber
- LEFT JOIN biblioitems on items.biblionumber=biblioitems.biblionumber
- WHERE itemcallnumber>= ?
- AND itemcallnumber <=?
- AND (datelastseen< ? OR datelastseen IS NULL)";
- $query.= " AND items.location=".$dbh->quote($location) if $location;
- $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch;
- $query.= " AND biblioitems.itemtype=".$dbh->quote($itemtype) if $itemtype;
- $query .= " ORDER BY itemcallnumber,title";
- $sth = $dbh->prepare($query);
- $sth->execute( $minlocation, $maxlocation, $datelastseen );
+ $datelastseen = format_date_in_iso($datelastseen);
+ push @where_strings, '(datelastseen < ? OR datelastseen IS NULL)';
+ push @bind_params, $datelastseen;
}
- else {
- my $query ="
- SELECT itemnumber,barcode,itemcallnumber,biblio.biblionumber,title,author,datelastseen
- FROM items
- LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber
- LEFT JOIN biblioitems on items.biblionumber=biblioitems.biblionumber
- WHERE itemcallnumber>= ?
- AND itemcallnumber <=?";
- $query.= " AND items.location=".$dbh->quote($location) if $location;
- $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch;
- $query.= " AND biblioitems.itemtype=".$dbh->quote($itemtype) if $itemtype;
- $query .= " ORDER BY itemcallnumber,title";
- $sth = $dbh->prepare($query);
- $sth->execute( $minlocation, $maxlocation );
+
+ if ( $location ) {
+ push @where_strings, 'items.location = ?';
+ push @bind_params, $location;
+ }
+
+ if ( $branchcode ) {
+ if($branch eq "homebranch"){
+ push @where_strings, 'items.homebranch = ?';
+ }else{
+ push @where_strings, 'items.holdingbranch = ?';
+ }
+ push @bind_params, $branchcode;
+ }
+
+ if ( $itemtype ) {
+ push @where_strings, 'biblioitems.itemtype = ?';
+ push @bind_params, $itemtype;
+ }
+
+ if ( $ignoreissued) {
+ $query .= "LEFT JOIN issues ON items.itemnumber = issues.itemnumber ";
+ push @where_strings, 'issues.date_due IS NULL';
+ }
+
+ if ( @where_strings ) {
+ $query .= 'WHERE ';
+ $query .= join ' AND ', @where_strings;
}
+ $query .= ' ORDER BY items.cn_sort, itemcallnumber, title';
+ my $sth = $dbh->prepare($query);
+ $sth->execute( @bind_params );
+
my @results;
$size--;
while ( my $row = $sth->fetchrow_hashref ) {
=head2 GetItemsCount
-=over 4
-$count = &GetItemsCount( $biblionumber);
-
-=back
+ $count = &GetItemsCount( $biblionumber);
This function return count of item with $biblionumber
my $sth = $dbh->prepare($query);
$sth->execute($biblionumber);
my $count = $sth->fetchrow;
- $sth->finish;
return ($count);
}
=head2 GetItemInfosOf
-=over 4
-
-GetItemInfosOf(@itemnumbers);
-
-=back
+ GetItemInfosOf(@itemnumbers);
=cut
=head2 GetItemsByBiblioitemnumber
-=over 4
-
-GetItemsByBiblioitemnumber($biblioitemnumber);
-
-=back
+ GetItemsByBiblioitemnumber($biblioitemnumber);
Returns an arrayref of hashrefs suitable for use in a TMPL_LOOP
Called by C<C4::XISBN>
# Foreach item, get circulation information
my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers
WHERE itemnumber = ?
- AND returndate is NULL
AND issues.borrowernumber = borrowers.borrowernumber"
);
$sth2->execute( $data->{'itemnumber'} );
# set date_due to blank, so in the template we check itemlost, and wthdrawn
$data->{'date_due'} = '';
} # else
- $sth2->finish;
# Find the last 3 people who borrowed this item.
- my $query2 = "SELECT * FROM issues, borrowers WHERE itemnumber = ?
- AND issues.borrowernumber = borrowers.borrowernumber
- AND returndate is not NULL
+ my $query2 = "SELECT * FROM old_issues, borrowers WHERE itemnumber = ?
+ AND old_issues.borrowernumber = borrowers.borrowernumber
ORDER BY returndate desc,timestamp desc LIMIT 3";
$sth2 = $dbh->prepare($query2) || die $dbh->errstr;
$sth2->execute( $data->{'itemnumber'} ) || die $sth2->errstr;
$data->{"borrower$i2"} = $data2->{'borrowernumber'};
$i2++;
}
- $sth2->finish;
push(@results,$data);
}
- $sth->finish;
return (\@results);
}
=head2 GetItemsInfo
-=over 4
-
-@results = GetItemsInfo($biblionumber, $type);
-
-=back
+ @results = GetItemsInfo($biblionumber, $type);
Returns information about books with the given biblionumber.
sub GetItemsInfo {
my ( $biblionumber, $type ) = @_;
my $dbh = C4::Context->dbh;
- my $query = "SELECT *,items.notforloan as itemnotforloan
- FROM items
- LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
- LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber";
- $query .= (C4::Context->preference('item-level_itypes')) ?
- " LEFT JOIN itemtypes on items.itype = itemtypes.itemtype "
- : " LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype ";
- $query .= "WHERE items.biblionumber = ? ORDER BY items.dateaccessioned desc" ;
+ # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance.
+ my $query = "
+ SELECT items.*,
+ biblio.*,
+ biblioitems.volume,
+ biblioitems.number,
+ biblioitems.itemtype,
+ biblioitems.isbn,
+ biblioitems.issn,
+ biblioitems.publicationyear,
+ biblioitems.publishercode,
+ biblioitems.volumedate,
+ biblioitems.volumedesc,
+ biblioitems.lccn,
+ biblioitems.url,
+ items.notforloan as itemnotforloan,
+ itemtypes.description,
+ itemtypes.notforloan as notforloan_per_itemtype,
+ branchurl
+ FROM items
+ LEFT JOIN branches ON items.homebranch = branches.branchcode
+ LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+ LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+ LEFT JOIN itemtypes ON itemtypes.itemtype = "
+ . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
+ $query .= " WHERE items.biblionumber = ? ORDER BY branches.branchname,items.dateaccessioned desc" ;
my $sth = $dbh->prepare($query);
$sth->execute($biblionumber);
my $i = 0;
my @results;
- my ( $date_due, $count_reserves, $serial );
+ my $serial;
my $isth = $dbh->prepare(
"SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode
FROM issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber
- WHERE itemnumber = ?
- AND returndate IS NULL"
+ WHERE itemnumber = ?"
);
my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=? ");
while ( my $data = $sth->fetchrow_hashref ) {
my $datedue = '';
+ my $count_reserves;
$isth->execute( $data->{'itemnumber'} );
if ( my $idata = $isth->fetchrow_hashref ) {
$data->{borrowernumber} = $idata->{borrowernumber};
$datedue = $idata->{'date_due'};
if (C4::Context->preference("IndependantBranches")){
my $userenv = C4::Context->userenv;
- if ( ($userenv) && ( $userenv->{flags} != 1 ) ) {
+ if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) {
$data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
}
}
if ( $datedue eq '' ) {
my ( $restype, $reserves ) =
C4::Reserves::CheckReserves( $data->{'itemnumber'} );
- if ($restype) {
- $count_reserves = $restype;
- }
+# Previous conditional check with if ($restype) is not needed because a true
+# result for one item will result in subsequent items defaulting to this true
+# value.
+ $count_reserves = $restype;
}
- $isth->finish;
- $ssth->finish;
#get branch information.....
my $bsth = $dbh->prepare(
"SELECT * FROM branches WHERE branchcode = ?
$data->{notforloanvalue} = $lib;
}
+ # get restricted status and description if applicable
+ my $restrictedstatus = $dbh->prepare(
+ 'SELECT authorised_value
+ FROM marc_subfield_structure
+ WHERE kohafield="items.restricted"
+ '
+ );
+
+ $restrictedstatus->execute;
+ ($authorised_valuecode) = $restrictedstatus->fetchrow;
+ if ($authorised_valuecode) {
+ $restrictedstatus = $dbh->prepare(
+ "SELECT lib,lib_opac FROM authorised_values
+ WHERE category=?
+ AND authorised_value=?"
+ );
+ $restrictedstatus->execute( $authorised_valuecode,
+ $data->{restricted} );
+
+ if ( my $rstdata = $restrictedstatus->fetchrow_hashref ) {
+ $data->{restricted} = $rstdata->{'lib'};
+ $data->{restrictedopac} = $rstdata->{'lib_opac'};
+ }
+ }
+
# my stack procedures
my $stackstatus = $dbh->prepare(
'SELECT authorised_value
$data->{stack} = $lib;
}
# Find the last 3 people who borrowed this item.
- my $sth2 = $dbh->prepare("SELECT * FROM issues,borrowers
+ my $sth2 = $dbh->prepare("SELECT * FROM old_issues,borrowers
WHERE itemnumber = ?
- AND issues.borrowernumber = borrowers.borrowernumber
- AND returndate IS NOT NULL LIMIT 3");
+ AND old_issues.borrowernumber = borrowers.borrowernumber
+ ORDER BY returndate DESC
+ LIMIT 3");
$sth2->execute($data->{'itemnumber'});
my $ii = 0;
while (my $data2 = $sth2->fetchrow_hashref()) {
$results[$i] = $data;
$i++;
}
- $sth->finish;
if($serial) {
- return( sort { $b->{'publisheddate'} cmp $a->{'publisheddate'} } @results );
+ return( sort { ($b->{'publisheddate'} || $b->{'enumchron'}) cmp ($a->{'publisheddate'} || $a->{'enumchron'}) } @results );
} else {
return (@results);
}
}
-=head2 get_itemnumbers_of
+=head2 GetLastAcquisitions
-=over 4
+ my $lastacq = GetLastAcquisitions({'branches' => ('branch1','branch2'),
+ 'itemtypes' => ('BK','BD')}, 10);
-my @itemnumbers_of = get_itemnumbers_of(@biblionumbers);
+=cut
-=back
+sub GetLastAcquisitions {
+ my ($data,$max) = @_;
+
+ my $itemtype = C4::Context->preference('item-level_itypes') ? 'itype' : 'itemtype';
+
+ my $number_of_branches = @{$data->{branches}};
+ my $number_of_itemtypes = @{$data->{itemtypes}};
+
+
+ my @where = ('WHERE 1 ');
+ $number_of_branches and push @where
+ , 'AND holdingbranch IN ('
+ , join(',', ('?') x $number_of_branches )
+ , ')'
+ ;
+
+ $number_of_itemtypes and push @where
+ , "AND $itemtype IN ("
+ , join(',', ('?') x $number_of_itemtypes )
+ , ')'
+ ;
+
+ my $query = "SELECT biblio.biblionumber as biblionumber, title, dateaccessioned
+ FROM items RIGHT JOIN biblio ON (items.biblionumber=biblio.biblionumber)
+ RIGHT JOIN biblioitems ON (items.biblioitemnumber=biblioitems.biblioitemnumber)
+ @where
+ GROUP BY biblio.biblionumber
+ ORDER BY dateaccessioned DESC LIMIT $max";
+
+ my $dbh = C4::Context->dbh;
+ my $sth = $dbh->prepare($query);
+
+ $sth->execute((@{$data->{branches}}, @{$data->{itemtypes}}));
+
+ my @results;
+ while( my $row = $sth->fetchrow_hashref){
+ push @results, {date => $row->{dateaccessioned}
+ , biblionumber => $row->{biblionumber}
+ , title => $row->{title}};
+ }
+
+ return @results;
+}
+
+=head2 get_itemnumbers_of
+
+ my @itemnumbers_of = get_itemnumbers_of(@biblionumbers);
Given a list of biblionumbers, return the list of corresponding itemnumbers
for each biblionumber.
=head2 GetItemnumberFromBarcode
-=over 4
-
-$result = GetItemnumberFromBarcode($barcode);
-
-=back
+ $result = GetItemnumberFromBarcode($barcode);
=cut
return ($result);
}
+=head2 GetBarcodeFromItemnumber
+
+ $result = GetBarcodeFromItemnumber($itemnumber);
+
+=cut
+
+sub GetBarcodeFromItemnumber {
+ my ($itemnumber) = @_;
+ my $dbh = C4::Context->dbh;
+
+ my $rq =
+ $dbh->prepare("SELECT barcode FROM items WHERE items.itemnumber=?");
+ $rq->execute($itemnumber);
+ my ($result) = $rq->fetchrow;
+ return ($result);
+}
+
+=head3 get_item_authorised_values
+
+find the types and values for all authorised values assigned to this item.
+
+parameters: itemnumber
+
+returns: a hashref malling the authorised value to the value set for this itemnumber
+
+ $authorised_values = {
+ 'CCODE' => undef,
+ 'DAMAGED' => '0',
+ 'LOC' => '3',
+ 'LOST' => '0'
+ 'NOT_LOAN' => '0',
+ 'RESTRICTED' => undef,
+ 'STACK' => undef,
+ 'WITHDRAWN' => '0',
+ 'branches' => 'CPL',
+ 'cn_source' => undef,
+ 'itemtypes' => 'SER',
+ };
+
+Notes: see C4::Biblio::get_biblio_authorised_values for a similar method at the biblio level.
+
+=cut
+
+sub get_item_authorised_values {
+ my $itemnumber = shift;
+
+ # assume that these entries in the authorised_value table are item level.
+ my $query = q(SELECT distinct authorised_value, kohafield
+ FROM marc_subfield_structure
+ WHERE kohafield like 'item%'
+ AND authorised_value != '' );
+
+ my $itemlevel_authorised_values = C4::Context->dbh->selectall_hashref( $query, 'authorised_value' );
+ my $iteminfo = GetItem( $itemnumber );
+ # warn( Data::Dumper->Dump( [ $itemlevel_authorised_values ], [ 'itemlevel_authorised_values' ] ) );
+ my $return;
+ foreach my $this_authorised_value ( keys %$itemlevel_authorised_values ) {
+ my $field = $itemlevel_authorised_values->{ $this_authorised_value }->{'kohafield'};
+ $field =~ s/^items\.//;
+ if ( exists $iteminfo->{ $field } ) {
+ $return->{ $this_authorised_value } = $iteminfo->{ $field };
+ }
+ }
+ # warn( Data::Dumper->Dump( [ $return ], [ 'return' ] ) );
+ return $return;
+}
+
+=head3 get_authorised_value_images
+
+find a list of icons that are appropriate for display based on the
+authorised values for a biblio.
+
+parameters: listref of authorised values, such as comes from
+get_item_authorised_values or
+from C4::Biblio::get_biblio_authorised_values
+
+returns: listref of hashrefs for each image. Each hashref looks like this:
+
+ { imageurl => '/intranet-tmpl/prog/img/itemtypeimg/npl/WEB.gif',
+ label => '',
+ category => '',
+ value => '', }
+
+Notes: Currently, I put on the full path to the images on the staff
+side. This should either be configurable or not done at all. Since I
+have to deal with 'intranet' or 'opac' in
+get_biblio_authorised_values, perhaps I should be passing it in.
+
+=cut
+
+sub get_authorised_value_images {
+ my $authorised_values = shift;
+
+ my @imagelist;
+
+ my $authorised_value_list = GetAuthorisedValues();
+ # warn ( Data::Dumper->Dump( [ $authorised_value_list ], [ 'authorised_value_list' ] ) );
+ foreach my $this_authorised_value ( @$authorised_value_list ) {
+ if ( exists $authorised_values->{ $this_authorised_value->{'category'} }
+ && $authorised_values->{ $this_authorised_value->{'category'} } eq $this_authorised_value->{'authorised_value'} ) {
+ # warn ( Data::Dumper->Dump( [ $this_authorised_value ], [ 'this_authorised_value' ] ) );
+ if ( defined $this_authorised_value->{'imageurl'} ) {
+ push @imagelist, { imageurl => C4::Koha::getitemtypeimagelocation( 'intranet', $this_authorised_value->{'imageurl'} ),
+ label => $this_authorised_value->{'lib'},
+ category => $this_authorised_value->{'category'},
+ value => $this_authorised_value->{'authorised_value'}, };
+ }
+ }
+ }
+
+ # warn ( Data::Dumper->Dump( [ \@imagelist ], [ 'imagelist' ] ) );
+ return \@imagelist;
+
+}
+
=head1 LIMITED USE FUNCTIONS
The following functions, while part of the public API,
=head2 GetMarcItem
-=over 4
-
-my $item_marc = GetMarcItem($biblionumber, $itemnumber);
-
-=back
+ my $item_marc = GetMarcItem($biblionumber, $itemnumber);
Returns MARC::Record of the item passed in parameter.
This function is meant for use only in C<cataloguing/additem.pl>,
# Tack on 'items.' prefix to column names so that TransformKohaToMarc will work.
# Also, don't emit a subfield if the underlying field is blank.
- my $mungeditem = { map { $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : () } keys %{ $itemrecord } };
+
+
+ return Item2Marc($itemrecord,$biblionumber);
+
+}
+sub Item2Marc {
+ my ($itemrecord,$biblionumber)=@_;
+ my $mungeditem = {
+ map {
+ defined($itemrecord->{$_}) && $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()
+ } keys %{ $itemrecord }
+ };
my $itemmarc = TransformKohaToMarc($mungeditem);
+ my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField("items.itemnumber",GetFrameworkCode($biblionumber)||'');
my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'});
if (defined $unlinked_item_subfields and $#$unlinked_item_subfields > -1) {
- my @fields = $itemmarc->fields();
- if ($#fields > -1) {
- $fields[0]->add_subfields(@$unlinked_item_subfields);
+ foreach my $field ($itemmarc->field($itemtag)){
+ $field->add_subfields(@$unlinked_item_subfields);
}
}
-
- return $itemmarc;
-
+ return $itemmarc;
}
=head1 PRIVATE FUNCTIONS AND VARIABLES
=head2 _set_derived_columns_for_add
-=over 4
-
-_set_derived_column_for_add($item);
-
-=back
+ _set_derived_column_for_add($item);
Given an item hash representing a new item to be added,
calculate any derived columns. Currently the only
=head2 _set_derived_columns_for_mod
-=over 4
-
-_set_derived_column_for_mod($item);
-
-=back
+ _set_derived_column_for_mod($item);
Given an item hash representing a new item to be modified.
calculate any derived columns. Currently the only
=head2 _do_column_fixes_for_mod
-=over 4
-
-_do_column_fixes_for_mod($item);
-
-=back
+ _do_column_fixes_for_mod($item);
Given an item hashref containing one or more
columns to modify, fix up certain values.
(not defined $item->{'wthdrawn'} or $item->{'wthdrawn'} eq '')) {
$item->{'wthdrawn'} = 0;
}
+ if (exists $item->{'location'} && !exists $item->{'permanent_location'}) {
+ $item->{'permanent_location'} = $item->{'location'};
+ }
+ if (exists $item->{'timestamp'}) {
+ delete $item->{'timestamp'};
+ }
}
=head2 _get_single_item_column
-=over 4
-
-_get_single_item_column($column, $itemnumber);
-
-=back
+ _get_single_item_column($column, $itemnumber);
Retrieves the value of a single column from an C<items>
row specified by C<$itemnumber>.
=head2 _calc_items_cn_sort
-=over 4
-
-_calc_items_cn_sort($item, $source_values);
-
-=back
+ _calc_items_cn_sort($item, $source_values);
Helper routine to calculate C<items.cn_sort>.
=head2 _set_defaults_for_add
-=over 4
-
-_set_defaults_for_add($item_hash);
-
-=back
+ _set_defaults_for_add($item_hash);
Given an item hash representing an item to be added, set
correct default values for columns whose default value
sub _set_defaults_for_add {
my $item = shift;
-
- # if dateaccessioned is provided, use it. Otherwise, set to NOW()
- if (!(exists $item->{'dateaccessioned'}) ||
- ($item->{'dateaccessioned'} eq '')) {
- # FIXME add check for invalid date
- my $today = C4::Dates->new();
- $item->{'dateaccessioned'} = $today->output("iso"); #TODO: check time issues
- }
-
- # various item status fields cannot be null
- $item->{'notforloan'} = 0 unless exists $item->{'notforloan'} and defined $item->{'notforloan'} and $item->{'notforloan'} ne '';
- $item->{'damaged'} = 0 unless exists $item->{'damaged'} and defined $item->{'damaged'} and $item->{'damaged'} ne '';
- $item->{'itemlost'} = 0 unless exists $item->{'itemlost'} and defined $item->{'itemlost'} and $item->{'itemlost'} ne '';
- $item->{'wthdrawn'} = 0 unless exists $item->{'wthdrawn'} and defined $item->{'wthdrawn'} and $item->{'wthdrawn'} ne '';
+ $item->{dateaccessioned} ||= C4::Dates->new->output('iso');
+ $item->{$_} ||= 0 for (qw( notforloan damaged itemlost wthdrawn));
}
=head2 _koha_new_item
-=over 4
-
-my ($itemnumber,$error) = _koha_new_item( $item, $barcode );
-
-=back
+ my ($itemnumber,$error) = _koha_new_item( $item, $barcode );
Perform the actual insert into the C<items> table.
ccode = ?,
itype = ?,
materials = ?,
- uri = ?,
- more_subfields_xml = ?
+ uri = ?,
+ enumchron = ?,
+ more_subfields_xml = ?,
+ copynumber = ?
";
my $sth = $dbh->prepare($query);
$sth->execute(
$item->{'itype'},
$item->{'materials'},
$item->{'uri'},
+ $item->{'enumchron'},
$item->{'more_subfields_xml'},
+ $item->{'copynumber'},
);
my $itemnumber = $dbh->{'mysql_insertid'};
if ( defined $sth->errstr ) {
$error.="ERROR in _koha_new_item $query".$sth->errstr;
}
- $sth->finish();
return ( $itemnumber, $error );
}
-=head2 _koha_modify_item
+=head2 MoveItemFromBiblio
-=over 4
+ MoveItemFromBiblio($itenumber, $frombiblio, $tobiblio);
-my ($itemnumber,$error) =_koha_modify_item( $item );
+Moves an item from a biblio to another
-=back
+Returns undef if the move failed or the biblionumber of the destination record otherwise
+
+=cut
+
+sub MoveItemFromBiblio {
+ my ($itemnumber, $frombiblio, $tobiblio) = @_;
+ my $dbh = C4::Context->dbh;
+ my $sth = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber = ?");
+ $sth->execute( $tobiblio );
+ my ( $tobiblioitem ) = $sth->fetchrow();
+ $sth = $dbh->prepare("UPDATE items SET biblioitemnumber = ?, biblionumber = ? WHERE itemnumber = ? AND biblionumber = ?");
+ my $return = $sth->execute($tobiblioitem, $tobiblio, $itemnumber, $frombiblio);
+ if ($return == 1) {
+
+ # Getting framework
+ my $frameworkcode = GetFrameworkCode($frombiblio);
+
+ # Getting marc field for itemnumber
+ my ($itemtag, $itemsubfield) = GetMarcFromKohaField('items.itemnumber', $frameworkcode);
+
+ # Getting the record we want to move the item from
+ my $record = GetMarcBiblio($frombiblio);
+
+ # The item we want to move
+ my $item;
+
+ # For each item
+ foreach my $fielditem ($record->field($itemtag)){
+ # If it is the item we want to move
+ if ($fielditem->subfield($itemsubfield) == $itemnumber) {
+ # We save it
+ $item = $fielditem;
+ # Then delete it from the record
+ $record->delete_field($fielditem)
+ }
+ }
+
+ # If we found an item (should always true, except in case of database-marcxml inconsistency)
+ if ($item) {
+
+ # Checking if the item we want to move is in an order
+ my $order = GetOrderFromItemnumber($itemnumber);
+ if ($order) {
+ # Replacing the biblionumber within the order if necessary
+ $order->{'biblionumber'} = $tobiblio;
+ ModOrder($order);
+ }
+
+ # Saving the modification
+ ModBiblioMarc($record, $frombiblio, $frameworkcode);
+
+ # Getting the record we want to move the item to
+ $record = GetMarcBiblio($tobiblio);
+
+ # Inserting the previously saved item
+ $record->insert_fields_ordered($item);
+
+ # Saving the modification
+ ModBiblioMarc($record, $tobiblio, $frameworkcode);
+
+ } else {
+ return undef;
+ }
+ } else {
+ return undef;
+ }
+}
+
+=head2 DelItemCheck
+
+ DelItemCheck($dbh, $biblionumber, $itemnumber);
+
+Exported function (core API) for deleting an item record in Koha if there no current issue.
+
+=cut
+
+sub DelItemCheck {
+ my ( $dbh, $biblionumber, $itemnumber ) = @_;
+ my $error;
+
+ # check that there is no issue on this item before deletion.
+ my $sth=$dbh->prepare("select * from issues i where i.itemnumber=?");
+ $sth->execute($itemnumber);
+
+ my $item = GetItem($itemnumber);
+ my $onloan = $sth->fetchrow;
+ if ($onloan) {
+ $error = "book_on_loan";
+ }
+ elsif (C4::Context->preference("IndependantBranches") and (C4::Context->userenv->{branch} ne $item->{C4::Context->preference("HomeOrHoldingBranch")||'homebranch'})){
+ $error = "not_same_branch";
+ }
+ else {
+ if ($onloan){
+ $error = "book_on_loan"
+ }
+ else {
+ # check it doesnt have a waiting reserve
+ $sth=$dbh->prepare("SELECT * FROM reserves WHERE (found = 'W' or found = 'T') AND itemnumber = ?");
+ $sth->execute($itemnumber);
+ my $reserve=$sth->fetchrow;
+ if ($reserve) {
+ $error = "book_reserved";
+ }
+ else {
+ DelItem($dbh, $biblionumber, $itemnumber);
+ return 1;
+ }
+ }
+ }
+ return $error;
+}
+
+=head2 _koha_modify_item
+
+ my ($itemnumber,$error) =_koha_modify_item( $item );
Perform the actual update of the C<items> row. Note that this
routine accepts a hashref specifying the columns to update.
$error.="ERROR in _koha_modify_item $query".$dbh->errstr;
warn $error;
}
- $sth->finish();
return ($item->{'itemnumber'},$error);
}
=head2 _koha_delete_item
-=over 4
-
-_koha_delete_item( $dbh, $itemnum );
-
-=back
+ _koha_delete_item( $dbh, $itemnum );
Internal function to delete an item record from the koha tables
my $sth = $dbh->prepare("SELECT * FROM items WHERE itemnumber=?");
$sth->execute($itemnum);
my $data = $sth->fetchrow_hashref();
- $sth->finish();
my $query = "INSERT INTO deleteditems SET ";
my @bind = ();
foreach my $key ( keys %$data ) {
$query =~ s/\,$//;
$sth = $dbh->prepare($query);
$sth->execute(@bind);
- $sth->finish();
# delete from items table
$sth = $dbh->prepare("DELETE FROM items WHERE itemnumber=?");
$sth->execute($itemnum);
- $sth->finish();
return undef;
}
=head2 _marc_from_item_hash
-=over 4
-
-my $item_marc = _marc_from_item_hash($item, $frameworkcode[, $unlinked_item_subfields]);
-
-=back
+ my $item_marc = _marc_from_item_hash($item, $frameworkcode[, $unlinked_item_subfields]);
Given an item hash representing a complete item record,
create a C<MARC::Record> object containing an embedded
: () } keys %{ $item } };
my $item_marc = MARC::Record->new();
- foreach my $item_field (keys %{ $mungeditem }) {
- my ($tag, $subfield) = GetMarcFromKohaField($item_field, $frameworkcode);
- next unless defined $tag and defined $subfield; # skip if not mapped to MARC field
- if (my $field = $item_marc->field($tag)) {
- $field->add_subfields($subfield => $mungeditem->{$item_field});
- } else {
- my $add_subfields = [];
- if (defined $unlinked_item_subfields and ref($unlinked_item_subfields) eq 'ARRAY' and $#$unlinked_item_subfields > -1) {
- $add_subfields = $unlinked_item_subfields;
+ foreach my $item_field ( keys %{$mungeditem} ) {
+ my ( $tag, $subfield ) = GetMarcFromKohaField( $item_field, $frameworkcode );
+ next unless defined $tag and defined $subfield; # skip if not mapped to MARC field
+ my @values = split(/\s?\|\s?/, $mungeditem->{$item_field}, -1);
+ foreach my $value (@values){
+ if ( my $field = $item_marc->field($tag) ) {
+ $field->add_subfields( $subfield => $value );
+ } else {
+ my $add_subfields = [];
+ if (defined $unlinked_item_subfields and ref($unlinked_item_subfields) eq 'ARRAY' and $#$unlinked_item_subfields > -1) {
+ $add_subfields = $unlinked_item_subfields;
+ }
+ $item_marc->add_fields( $tag, " ", " ", $subfield => $value, @$add_subfields );
}
- $item_marc->add_fields( $tag, " ", " ", $subfield => $mungeditem->{$item_field}, @$add_subfields);
}
}
=head2 _add_item_field_to_biblio
-=over 4
-
-_add_item_field_to_biblio($item_marc, $biblionumber, $frameworkcode);
-
-=back
+ _add_item_field_to_biblio($item_marc, $biblionumber, $frameworkcode);
Adds the fields from a MARC record containing the
representation of a Koha item record to the MARC
my ($item_marc, $biblionumber, $frameworkcode) = @_;
my $biblio_marc = GetMarcBiblio($biblionumber);
-
foreach my $field ($item_marc->fields()) {
$biblio_marc->append_fields($field);
}
=head2 _replace_item_field_in_biblio
-=over
-
-&_replace_item_field_in_biblio($item_marc, $biblionumber, $itemnumber, $frameworkcode)
-
-=back
+ &_replace_item_field_in_biblio($item_marc, $biblionumber, $itemnumber, $frameworkcode)
Given a MARC::Record C<$item_marc> containing one tag with the MARC
representation of the item, examine the biblio MARC
=head2 _get_unlinked_item_subfields
-=over 4
-
-my $unlinked_item_subfields = _get_unlinked_item_subfields($original_item_marc, $frameworkcode);
-
-=back
+ my $unlinked_item_subfields = _get_unlinked_item_subfields($original_item_marc, $frameworkcode);
=cut
=head2 _get_unlinked_subfields_xml
-=over 4
-
-my $unlinked_subfields_xml = _get_unlinked_subfields_xml($unlinked_item_subfields);
-
-=back
+ my $unlinked_subfields_xml = _get_unlinked_subfields_xml($unlinked_item_subfields);
=cut
# use of tag 999 is arbitrary, and doesn't need to match the item tag
# used in the framework
$marc->append_fields(MARC::Field->new('999', ' ', ' ', @$unlinked_item_subfields));
- $xml = $marc->as_xml();
+ $marc->encoding("UTF-8");
+ $xml = $marc->as_xml("USMARC");
}
return $xml;
=head2 _parse_unlinked_item_subfields_from_xml
-=over 4
-
-my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($whole_item->{'more_subfields_xml'}):
-
-=back
+ my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($whole_item->{'more_subfields_xml'}):
=cut
my $xml = shift;
return unless defined $xml and $xml ne "";
- my $marc = MARC::Record->new_from_xml(StripNonXmlChars($xml), 'UTF-8', C4::Context->preference("marcflavour"));
+ my $marc = MARC::Record->new_from_xml(StripNonXmlChars($xml),'UTF-8');
my $unlinked_subfields = [];
my @fields = $marc->fields();
if ($#fields > -1) {