use C4::Dates qw/format_date/;
use C4::Log; # logaction
use C4::ClassSource;
-
use vars qw($VERSION @ISA @EXPORT);
# TODO: fix version
# EXPORTED FUNCTIONS.
# to add biblios or items
-push @EXPORT, qw( &AddBiblio &AddItem &AddBiblioAndItems );
+push @EXPORT, qw( &AddBiblio &AddBiblioAndItems );
# to get something
push @EXPORT, qw(
&GetBiblioItemByBiblioNumber
&GetBiblioFromItemNumber
- &GetMarcItem
- &GetItem
&GetItemInfosOf
&GetItemStatus
&GetItemLocation
# To modify something
push @EXPORT, qw(
&ModBiblio
- &ModItem
- &ModItemTransfer
&ModBiblioframework
&ModZebra
- &ModItemInMarc
- &ModItemInMarconefield
- &ModDateLastSeen
);
# To delete something
# but don't use them unless you're a core developer ;-)
push @EXPORT, qw(
&ModBiblioMarc
- &AddItemInMarc
);
# Others functions
warn "ERROR: cannot add item $item->{'barcode'} for biblio $biblionumber: duplicate barcode\n";
}
- # figure out what item type to use -- biblioitem-level or item-level
- my $itemtype;
- if (C4::Context->preference('item-level_itypes')) {
- $itemtype = $item->{'itype'};
- } else {
- $itemtype = $olddata->{'itemtype'};
- }
-
- # FIXME - notforloan stuff copied from AddItem
- my $sth = $dbh->prepare("SELECT notforloan FROM itemtypes WHERE itemtype=?");
- $sth->execute($itemtype);
- my $notforloan = $sth->fetchrow;
- ##Change the notforloan field if $notforloan found
- if ( $notforloan > 0 ) {
- $item->{'notforloan'} = $notforloan;
- &MARCitemchange( $temp_item_marc, "items.notforloan", $notforloan );
+ # Make sure item statuses are set to 0 if empty or NULL in both the item and the MARC
+ for ('notforloan', 'damaged','itemlost','wthdrawn') {
+ if (!$item->{$_} or $item->{$_} eq "") {
+ $item->{$_} = 0;
+ &MARCitemchange( $temp_item_marc, "items.$_", 0 );
+ }
}
-
+
# FIXME - dateaccessioned stuff copied from AddItem
if ( !$item->{'dateaccessioned'} || $item->{'dateaccessioned'} eq '' ) {
return @repacked_errors;
}
-=head2 AddItem
-
-=over 2
-
- $biblionumber = AddItem( $record, $biblionumber)
- Exported function (core API) for adding a new item to Koha
-
-=back
-
-=cut
-
-sub AddItem {
- my ( $record, $biblionumber ) = @_;
- my $dbh = C4::Context->dbh;
-
- # add item in old-DB
- my $frameworkcode = GetFrameworkCode( $biblionumber );
- my $item = &TransformMarcToKoha( $dbh, $record, $frameworkcode );
-
- # needs old biblionumber and biblioitemnumber
- $item->{'biblionumber'} = $biblionumber;
- my $sth =
- $dbh->prepare(
- "SELECT biblioitemnumber,itemtype FROM biblioitems WHERE biblionumber=?"
- );
- $sth->execute( $item->{'biblionumber'} );
- my $itemtype;
- ( $item->{'biblioitemnumber'}, $itemtype ) = $sth->fetchrow;
- $sth =
- $dbh->prepare(
- "SELECT notforloan FROM itemtypes WHERE itemtype=?");
- $sth->execute( C4::Context->preference('item-level_itypes') ? $item->{'itype'} : $itemtype );
- my $notforloan = $sth->fetchrow;
- ##Change the notforloan field if $notforloan found
- if ( $notforloan > 0 ) {
- $item->{'notforloan'} = $notforloan;
- &MARCitemchange( $record, "items.notforloan", $notforloan );
- }
- if ( !$item->{'dateaccessioned'} || $item->{'dateaccessioned'} eq '' ) {
-
- # find today's date
- my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
- localtime(time);
- $year += 1900;
- $mon += 1;
- my $date =
- "$year-" . sprintf( "%0.2d", $mon ) . "-" . sprintf( "%0.2d", $mday );
- $item->{'dateaccessioned'} = $date;
- &MARCitemchange( $record, "items.dateaccessioned", $date );
- }
- my ( $itemnumber, $error ) = &_koha_new_items( $dbh, $item, $item->{barcode} );
- # add itemnumber to MARC::Record before adding the item.
- $sth = $dbh->prepare(
-"SELECT tagfield,tagsubfield
-FROM marc_subfield_structure
-WHERE frameworkcode=?
- AND kohafield=?"
- );
- &TransformKohaToMarcOneField( $sth, $record, "items.itemnumber", $itemnumber,
- $frameworkcode );
-
- # add the item
- &AddItemInMarc( $record, $item->{'biblionumber'},$frameworkcode );
-
- &logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$itemnumber,"item")
- if C4::Context->preference("CataloguingLog");
-
- return ($item->{biblionumber}, $item->{biblioitemnumber},$itemnumber);
-}
-
=head2 ModBiblio
ModBiblio( $record,$biblionumber,$frameworkcode);
return 1;
}
-=head2 ModItem
-
-=over 2
-
-Exported function (core API) for modifying an item in Koha.
-
-=back
-
-=cut
-
-sub ModItem {
- my ( $record, $biblionumber, $itemnumber, $delete, $new_item_hashref )
- = @_;
-
- #logging
- &logaction(C4::Context->userenv->{'number'},"CATALOGUING","MODIFY",$itemnumber,$record->as_formatted)
- if C4::Context->preference("CataloguingLog");
-
- my $dbh = C4::Context->dbh;
-
- # if we have a MARC record, we're coming from cataloging and so
- # we do the whole routine: update the MARC and zebra, then update the koha
- # tables
- if ($record) {
- my $frameworkcode = GetFrameworkCode( $biblionumber );
- ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
- my $olditem = TransformMarcToKoha( $dbh, $record, $frameworkcode,'items');
- $olditem->{'biblionumber'} = $biblionumber;
- my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
- $sth->execute($biblionumber);
- my ($biblioitemnumber) = $sth->fetchrow;
- $sth->finish();
- $olditem->{'biblioitemnumber'} = $biblioitemnumber;
- _koha_modify_item( $dbh, $olditem );
- return $biblionumber;
- }
-
- # otherwise, we're just looking to modify something quickly
- # (like a status) so we just update the koha tables
- elsif ($new_item_hashref) {
- _koha_modify_item( $dbh, $new_item_hashref );
- }
-}
-
-sub ModItemTransfer {
- my ( $itemnumber, $frombranch, $tobranch ) = @_;
-
- my $dbh = C4::Context->dbh;
-
- #new entry in branchtransfers....
- my $sth = $dbh->prepare(
- "INSERT INTO branchtransfers (itemnumber, frombranch, datesent, tobranch)
- VALUES (?, ?, NOW(), ?)");
- $sth->execute($itemnumber, $frombranch, $tobranch);
- #update holdingbranch in items .....
- $sth= $dbh->prepare(
- "UPDATE items SET holdingbranch = ? WHERE items.itemnumber = ?");
- $sth->execute($tobranch,$itemnumber);
- &ModDateLastSeen($itemnumber);
- $sth = $dbh->prepare(
- "SELECT biblionumber FROM items WHERE itemnumber=?"
- );
- $sth->execute($itemnumber);
- while ( my ( $biblionumber ) = $sth->fetchrow ) {
- &ModItemInMarconefield( $biblionumber, $itemnumber,
- 'items.holdingbranch', $tobranch );
- }
- return;
-}
-
=head2 ModBiblioframework
ModBiblioframework($biblionumber,$frameworkcode);
return 1;
}
-=head2 ModItemInMarconefield
-
-=over
-
-modify only 1 field in a MARC item (mainly used for holdingbranch, but could also be used for status modif - moving a book to "lost" on a long overdu for example)
-&ModItemInMarconefield( $biblionumber, $itemnumber, $itemfield, $newvalue )
-
-=back
-
-=cut
-
-sub ModItemInMarconefield {
- my ( $biblionumber, $itemnumber, $itemfield, $newvalue ) = @_;
- my $dbh = C4::Context->dbh;
- if ( !defined $newvalue ) {
- $newvalue = "";
- }
-
- my $record = GetMarcItem( $biblionumber, $itemnumber );
- my ($tagfield, $tagsubfield) = GetMarcFromKohaField( $itemfield,'');
- # FIXME - the condition is done this way because GetMarcFromKohaField
- # returns (0, 0) if it can't field a MARC tag for the kohafield. However,
- # some fields like items.wthdrawn are mapped to subfield $0, making the
- # customary test of "if ($tagfield && $tagsubfield)" incorrect.
- # GetMarcFromKohaField should probably be returning (undef, undef), making
- # the correct test "if (defined $tagfield && defined $tagsubfield)", but
- # this would be a large change and consequently deferred for after 3.0.
- if (not(int($tagfield) == 0 && int($tagsubfield) == 0)) {
- my $tag = $record->field($tagfield);
- if ($tag) {
-# my $tagsubs = $record->field($tagfield)->subfield($tagsubfield);
- $tag->update( $tagsubfield => $newvalue );
- $record->delete_field($tag);
- $record->insert_fields_ordered($tag);
- my $frameworkcode = GetFrameworkCode( $biblionumber );
- &ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
- }
- }
-}
-
-=head2 ModItemInMarc
-
-=over
-
-&ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode )
-
-=back
-
-=cut
-
-sub ModItemInMarc {
- my ( $ItemRecord, $biblionumber, $itemnumber, $frameworkcode) = @_;
- my $dbh = C4::Context->dbh;
-
- # get complete MARC record & replace the item field by the new one
- my $completeRecord = GetMarcBiblio($biblionumber);
- my ($itemtag,$itemsubfield) = GetMarcFromKohaField("items.itemnumber",$frameworkcode);
- my $itemField = $ItemRecord->field($itemtag);
- my @items = $completeRecord->field($itemtag);
- foreach (@items) {
- if ($_->subfield($itemsubfield) eq $itemnumber) {
-# $completeRecord->delete_field($_);
- $_->replace_with($itemField);
- }
- }
- # save the record
- my $sth = $dbh->prepare("UPDATE biblioitems SET marc=?,marcxml=? WHERE biblionumber=?");
- $sth->execute( $completeRecord->as_usmarc(), $completeRecord->as_xml_record(),$biblionumber );
- $sth->finish;
- ModZebra($biblionumber,"specialUpdate","biblioserver",$completeRecord);
-}
-
-=head2 ModDateLastSeen
-
-&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
-
-=cut
-
-sub ModDateLastSeen {
- my ($itemnum) = @_;
- my $dbh = C4::Context->dbh;
- my $sth =
- $dbh->prepare(
- "UPDATE items SET itemlost=0,datelastseen = NOW() WHERE items.itemnumber = ?"
- );
- $sth->execute($itemnum);
- return;
-}
=head2 DelBiblio
=over
return ( $count, @results );
} # sub GetBiblio
-=head2 GetItem
-
-=over 4
-
-$data = &GetItem($itemnumber,$barcode);
-
-return Item information, for a given itemnumber or barcode
-
-=back
-
-=cut
-
-sub GetItem {
- my ($itemnumber,$barcode) = @_;
- my $dbh = C4::Context->dbh;
- if ($itemnumber) {
- my $sth = $dbh->prepare("
- SELECT * FROM items
- WHERE itemnumber = ?");
- $sth->execute($itemnumber);
- my $data = $sth->fetchrow_hashref;
- return $data;
- } else {
- my $sth = $dbh->prepare("
- SELECT * FROM items
- WHERE barcode = ?"
- );
- $sth->execute($barcode);
- my $data = $sth->fetchrow_hashref;
- return $data;
- }
-} # sub GetItem
-
=head2 get_itemnumbers_of
=over 4
}
}
-=head2 GetMarcItem
-
-=over 4
-
-Returns MARC::Record of the item passed in parameter.
-
-=back
-
-=cut
-
-sub GetMarcItem {
- my ( $biblionumber, $itemnumber ) = @_;
-
- # GetMarcItem has been revised so that it does the following:
- # 1. Gets the item information from the items table.
- # 2. Converts it to a MARC field for storage in the bib record.
- #
- # The previous behavior was:
- # 1. Get the bib record.
- # 2. Return the MARC tag corresponding to the item record.
- #
- # The difference is that one treats the items row as authoritative,
- # while the other treats the MARC representation as authoritative
- # under certain circumstances.
- #
- # FIXME - a big one
- #
- # As of 2007-11-27, this change hopefully does not introduce
- # any bugs. However, it does mean that for code that uses
- # ModItemInMarconefield to update one subfield (corresponding to
- # an items column) is now less efficient.
- #
- # The API needs to be shifted to the following:
- # 1. User updates items record.
- # 2. Linked bib is sent for indexing.
- #
- # The missing step 1.5 is updating the item tag in the bib MARC record
- # so that the indexes are updated. Depending on performance considerations,
- # this may ultimately mean of of the following:
- # a. MARC field for item is updated right away.
- # b. MARC field for item is updated only as part of indexing.
- # c. MARC field for item is never actually stored in bib record; instead
- # it is generated only when needed for indexing, item export, and
- # (maybe) OPAC display.
- #
-
- my $itemrecord = GetItem($itemnumber);
-
- # 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 } };
-
- my $itemmarc = TransformKohaToMarc($mungeditem);
- return $itemmarc;
-
-}
-
-
-
=head2 GetMarcNotes
=over 4
}
$prevtag = @$tags[$i];
}
- if (C4::Context->preference('marcflavour') and !$unimarc_and_100_exist) {
+ if (C4::Context->preference('marcflavour') eq 'UNIMARC' and !$unimarc_and_100_exist) {
# warn "SETTING 100 for $auth_type";
use POSIX qw(strftime);
my $string = strftime( "%Y%m%d", localtime(time) );
}
# modify copyrightdate to keep only the 1st year found
- my $temp = $result->{'copyrightdate'};
- $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
- if ( $1 > 0 ) {
- $result->{'copyrightdate'} = $1;
- }
- else { # if no cYYYY, get the 1st date.
- $temp =~ m/(\d\d\d\d)/;
- $result->{'copyrightdate'} = $1;
+ if (exists $result->{'copyrightdate'}) {
+ my $temp = $result->{'copyrightdate'};
+ $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
+ if ( $1 > 0 ) {
+ $result->{'copyrightdate'} = $1;
+ }
+ else { # if no cYYYY, get the 1st date.
+ $temp =~ m/(\d\d\d\d)/;
+ $result->{'copyrightdate'} = $1;
+ }
}
# modify publicationyear to keep only the 1st year found
- $temp = $result->{'publicationyear'};
- $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
- if ( $1 > 0 ) {
- $result->{'publicationyear'} = $1;
- }
- else { # if no cYYYY, get the 1st date.
- $temp =~ m/(\d\d\d\d)/;
- $result->{'publicationyear'} = $1;
+ if (exists $result->{'publicationyear'}) {
+ my $temp = $result->{'publicationyear'};
+ $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
+ if ( $1 > 0 ) {
+ $result->{'publicationyear'} = $1;
+ }
+ else { # if no cYYYY, get the 1st date.
+ $temp =~ m/(\d\d\d\d)/;
+ $result->{'publicationyear'} = $1;
+ }
}
+
return $result;
}
my %indexes;
foreach my $line (split /('|"),/,$index) {
$line =~ /(.*)=>(.*)/;
-warn $line;
my $index = substr($1,1); # get the index, don't forget to remove initial ' or "
my $fields = $2;
$index =~ s/'|"|\s//g;
sub _koha_new_items {
my ( $dbh, $item, $barcode ) = @_;
my $error;
-
my ($items_cn_sort) = GetClassSort($item->{'items.cn_source'}, $item->{'itemcallnumber'}, "");
# if dateaccessioned is provided, use it. Otherwise, set to NOW()
return ( $itemnumber, $error );
}
-=head2 _koha_modify_item
-
-=over 4
-
-my ($itemnumber,$error) =_koha_modify_item( $dbh, $item, $op );
-
-=back
-
-=cut
-
-sub _koha_modify_item {
- my ( $dbh, $item ) = @_;
- my $error;
-
- # calculate items.cn_sort
- if($item->{'itemcallnumber'}) {
- # This works, even when user is setting the call number blank (in which case
- # how would we get here to calculate new (blank) of items.cn_sort?).
- #
- # Why? Because at present the only way to update itemcallnumber is via
- # additem.pl; since it uses a MARC data-entry form, TransformMarcToKoha
- # already has created $item->{'items.cn_sort'} and set it to undef because the
- # subfield for items.cn_sort in the framework is specified as ignored, meaning
- # that it is not supplied or passed to the form. Thus, if the user has
- # blanked itemcallnumber, there is already a undef value for $item->{'items.cn_sort'}.
- #
- # This is subtle; it is also fragile.
- $item->{'items.cn_sort'} = GetClassSort($item->{'items.cn_source'}, $item->{'itemcallnumber'}, "");
- }
- my $query = "UPDATE items SET ";
- my @bind;
- for my $key ( keys %$item ) {
- $query.="$key=?,";
- push @bind, $item->{$key};
- }
- $query =~ s/,$//;
- $query .= " WHERE itemnumber=?";
- push @bind, $item->{'itemnumber'};
- my $sth = $dbh->prepare($query);
- $sth->execute(@bind);
- if ( $dbh->errstr ) {
- $error.="ERROR in _koha_modify_item $query".$dbh->errstr;
- warn $error;
- }
- $sth->finish();
- return ($item->{'itemnumber'},$error);
-}
-
=head2 _koha_delete_biblio
=over 4
return $biblionumber;
}
-=head2 AddItemInMarc
-
-=over 4
-
-$newbiblionumber = AddItemInMarc( $record, $biblionumber, $frameworkcode );
-
-Add an item in a MARC record and save the MARC record
-
-Function exported, but should NOT be used, unless you really know what you're doing
-
-=back
-
-=cut
-
-sub AddItemInMarc {
-
- # pass the MARC::Record to this function, and it will create the records in the marc tables
- my ( $record, $biblionumber, $frameworkcode ) = @_;
- my $newrec = &GetMarcBiblio($biblionumber);
-
- # create it
- my @fields = $record->fields();
- foreach my $field (@fields) {
- $newrec->append_fields($field);
- }
-
- # FIXME: should we be making sure the biblionumbers are the same?
- my $newbiblionumber =
- &ModBiblioMarc( $newrec, $biblionumber, $frameworkcode );
- return $newbiblionumber;
-}
-
=head2 z3950_extended_services
z3950_extended_services($serviceType,$serviceOptions,$record);