| Filename | /usr/share/koha/lib/C4/Items.pm |
| Statements | Executed 1577 statements in 285ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 25 | 1 | 1 | 12.4ms | 832ms | C4::Items::GetItemsInfo |
| 32 | 1 | 1 | 1.90ms | 122ms | C4::Items::GetHiddenItemnumbers |
| 1 | 1 | 1 | 37µs | 47µs | C4::Items::BEGIN@21 |
| 1 | 1 | 1 | 22µs | 22µs | C4::Items::BEGIN@38 |
| 1 | 1 | 1 | 20µs | 26µs | C4::Items::BEGIN@25 |
| 1 | 1 | 1 | 20µs | 566µs | C4::Items::BEGIN@27 |
| 1 | 1 | 1 | 17µs | 57µs | C4::Items::BEGIN@32 |
| 1 | 1 | 1 | 15µs | 36µs | C4::Items::BEGIN@29 |
| 1 | 1 | 1 | 15µs | 70µs | C4::Items::BEGIN@28 |
| 1 | 1 | 1 | 14µs | 446µs | C4::Items::BEGIN@26 |
| 1 | 1 | 1 | 14µs | 46µs | C4::Items::BEGIN@33 |
| 1 | 1 | 1 | 13µs | 73µs | C4::Items::BEGIN@24 |
| 1 | 1 | 1 | 12µs | 117µs | C4::Items::BEGIN@31 |
| 1 | 1 | 1 | 12µs | 188µs | C4::Items::BEGIN@30 |
| 1 | 1 | 1 | 11µs | 77µs | C4::Items::BEGIN@36 |
| 0 | 0 | 0 | 0s | 0s | C4::Items::AddItem |
| 0 | 0 | 0 | 0s | 0s | C4::Items::AddItemBatchFromMarc |
| 0 | 0 | 0 | 0s | 0s | C4::Items::AddItemFromMarc |
| 0 | 0 | 0 | 0s | 0s | C4::Items::CartToShelf |
| 0 | 0 | 0 | 0s | 0s | C4::Items::CheckItemPreSave |
| 0 | 0 | 0 | 0s | 0s | C4::Items::DelItem |
| 0 | 0 | 0 | 0s | 0s | C4::Items::DelItemCheck |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetAnalyticsCount |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetBarcodeFromItemnumber |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetHostItemsInfo |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItem |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemHolds |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemInfosOf |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemLocation |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemStatus |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemnumberFromBarcode |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemnumbersForBiblio |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemsByBiblioitemnumber |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemsCount |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemsForInventory |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetItemsLocationInfo |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetLastAcquisitions |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetLostItems |
| 0 | 0 | 0 | 0s | 0s | C4::Items::GetMarcItem |
| 0 | 0 | 0 | 0s | 0s | C4::Items::Item2Marc |
| 0 | 0 | 0 | 0s | 0s | C4::Items::ModDateLastSeen |
| 0 | 0 | 0 | 0s | 0s | C4::Items::ModItem |
| 0 | 0 | 0 | 0s | 0s | C4::Items::ModItemFromMarc |
| 0 | 0 | 0 | 0s | 0s | C4::Items::ModItemTransfer |
| 0 | 0 | 0 | 0s | 0s | C4::Items::MoveItemFromBiblio |
| 0 | 0 | 0 | 0s | 0s | C4::Items::PrepareItemrecordDisplay |
| 0 | 0 | 0 | 0s | 0s | C4::Items::SearchItems |
| 0 | 0 | 0 | 0s | 0s | C4::Items::ShelfToCart |
| 0 | 0 | 0 | 0s | 0s | C4::Items::__ANON__[:1668] |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_calc_items_cn_sort |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_do_column_fixes_for_mod |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_find_value |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_get_items_columns |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_get_single_item_column |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_get_unlinked_item_subfields |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_get_unlinked_subfields_xml |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_koha_delete_item |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_koha_modify_item |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_koha_new_item |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_marc_from_item_hash |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_parse_unlinked_item_subfields_from_xml |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_repack_item_errors |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_set_defaults_for_add |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_set_derived_columns_for_add |
| 0 | 0 | 0 | 0s | 0s | C4::Items::_set_derived_columns_for_mod |
| 0 | 0 | 0 | 0s | 0s | C4::Items::get_authorised_value_images |
| 0 | 0 | 0 | 0s | 0s | C4::Items::get_hostitemnumbers_of |
| 0 | 0 | 0 | 0s | 0s | C4::Items::get_item_authorised_values |
| 0 | 0 | 0 | 0s | 0s | C4::Items::get_itemnumbers_of |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package C4::Items; | ||||
| 2 | |||||
| 3 | # Copyright 2007 LibLime, Inc. | ||||
| 4 | # Parts Copyright Biblibre 2010 | ||||
| 5 | # | ||||
| 6 | # This file is part of Koha. | ||||
| 7 | # | ||||
| 8 | # Koha is free software; you can redistribute it and/or modify it under the | ||||
| 9 | # terms of the GNU General Public License as published by the Free Software | ||||
| 10 | # Foundation; either version 2 of the License, or (at your option) any later | ||||
| 11 | # version. | ||||
| 12 | # | ||||
| 13 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| 14 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||||
| 15 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||||
| 16 | # | ||||
| 17 | # You should have received a copy of the GNU General Public License along | ||||
| 18 | # with Koha; if not, write to the Free Software Foundation, Inc., | ||||
| 19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
| 20 | |||||
| 21 | 3 | 109µs | 2 | 58µs | # spent 47µs (37+10) within C4::Items::BEGIN@21 which was called:
# once (37µs+10µs) by C4::Reserves::BEGIN@29 at line 21 # spent 47µs making 1 call to C4::Items::BEGIN@21
# spent 10µs making 1 call to strict::import |
| 22 | #use warnings; FIXME - Bug 2505 | ||||
| 23 | |||||
| 24 | 3 | 36µs | 2 | 133µs | # spent 73µs (13+60) within C4::Items::BEGIN@24 which was called:
# once (13µs+60µs) by C4::Reserves::BEGIN@29 at line 24 # spent 73µs making 1 call to C4::Items::BEGIN@24
# spent 60µs making 1 call to Exporter::import |
| 25 | 3 | 50µs | 2 | 32µs | # spent 26µs (20+6) within C4::Items::BEGIN@25 which was called:
# once (20µs+6µs) by C4::Reserves::BEGIN@29 at line 25 # spent 26µs making 1 call to C4::Items::BEGIN@25
# spent 6µs making 1 call to C4::Context::import |
| 26 | 3 | 46µs | 2 | 877µs | # spent 446µs (14+431) within C4::Items::BEGIN@26 which was called:
# once (14µs+431µs) by C4::Reserves::BEGIN@29 at line 26 # spent 446µs making 1 call to C4::Items::BEGIN@26
# spent 431µs making 1 call to Exporter::import |
| 27 | 3 | 80µs | 2 | 1.11ms | # spent 566µs (20+547) within C4::Items::BEGIN@27 which was called:
# once (20µs+547µs) by C4::Reserves::BEGIN@29 at line 27 # spent 566µs making 1 call to C4::Items::BEGIN@27
# spent 546µs making 1 call to Exporter::import |
| 28 | 3 | 33µs | 2 | 125µs | # spent 70µs (15+55) within C4::Items::BEGIN@28 which was called:
# once (15µs+55µs) by C4::Reserves::BEGIN@29 at line 28 # spent 70µs making 1 call to C4::Items::BEGIN@28
# spent 55µs making 1 call to Exporter::import |
| 29 | 3 | 34µs | 2 | 58µs | # spent 36µs (15+21) within C4::Items::BEGIN@29 which was called:
# once (15µs+21µs) by C4::Reserves::BEGIN@29 at line 29 # spent 36µs making 1 call to C4::Items::BEGIN@29
# spent 21µs making 1 call to Exporter::import |
| 30 | 3 | 34µs | 2 | 363µs | # spent 188µs (12+176) within C4::Items::BEGIN@30 which was called:
# once (12µs+176µs) by C4::Reserves::BEGIN@29 at line 30 # spent 188µs making 1 call to C4::Items::BEGIN@30
# spent 176µs making 1 call to Exporter::import |
| 31 | 3 | 36µs | 2 | 222µs | # spent 117µs (12+105) within C4::Items::BEGIN@31 which was called:
# once (12µs+105µs) by C4::Reserves::BEGIN@29 at line 31 # spent 117µs making 1 call to C4::Items::BEGIN@31
# spent 105µs making 1 call to Exporter::import |
| 32 | 3 | 37µs | 2 | 97µs | # spent 57µs (17+40) within C4::Items::BEGIN@32 which was called:
# once (17µs+40µs) by C4::Reserves::BEGIN@29 at line 32 # spent 57µs making 1 call to C4::Items::BEGIN@32
# spent 40µs making 1 call to Exporter::import |
| 33 | 3 | 36µs | 2 | 78µs | # spent 46µs (14+32) within C4::Items::BEGIN@33 which was called:
# once (14µs+32µs) by C4::Reserves::BEGIN@29 at line 33 # spent 46µs making 1 call to C4::Items::BEGIN@33
# spent 32µs making 1 call to Exporter::import |
| 34 | # debugging; so please don't remove this | ||||
| 35 | |||||
| 36 | 3 | 116µs | 2 | 143µs | # spent 77µs (11+66) within C4::Items::BEGIN@36 which was called:
# once (11µs+66µs) by C4::Reserves::BEGIN@29 at line 36 # spent 77µs making 1 call to C4::Items::BEGIN@36
# spent 66µs making 1 call to vars::import |
| 37 | |||||
| 38 | # spent 22µs within C4::Items::BEGIN@38 which was called:
# once (22µs+0s) by C4::Reserves::BEGIN@29 at line 90 | ||||
| 39 | 4 | 22µs | $VERSION = 3.07.00.049; | ||
| 40 | |||||
| 41 | require Exporter; | ||||
| 42 | @ISA = qw( Exporter ); | ||||
| 43 | |||||
| 44 | # function exports | ||||
| 45 | @EXPORT = qw( | ||||
| 46 | GetItem | ||||
| 47 | AddItemFromMarc | ||||
| 48 | AddItem | ||||
| 49 | AddItemBatchFromMarc | ||||
| 50 | ModItemFromMarc | ||||
| 51 | Item2Marc | ||||
| 52 | ModItem | ||||
| 53 | ModDateLastSeen | ||||
| 54 | ModItemTransfer | ||||
| 55 | DelItem | ||||
| 56 | |||||
| 57 | CheckItemPreSave | ||||
| 58 | |||||
| 59 | GetItemStatus | ||||
| 60 | GetItemLocation | ||||
| 61 | GetLostItems | ||||
| 62 | GetItemsForInventory | ||||
| 63 | GetItemsCount | ||||
| 64 | GetItemInfosOf | ||||
| 65 | GetItemsByBiblioitemnumber | ||||
| 66 | GetItemsInfo | ||||
| 67 | GetItemsLocationInfo | ||||
| 68 | GetHostItemsInfo | ||||
| 69 | GetItemnumbersForBiblio | ||||
| 70 | get_itemnumbers_of | ||||
| 71 | get_hostitemnumbers_of | ||||
| 72 | GetItemnumberFromBarcode | ||||
| 73 | GetBarcodeFromItemnumber | ||||
| 74 | GetHiddenItemnumbers | ||||
| 75 | DelItemCheck | ||||
| 76 | MoveItemFromBiblio | ||||
| 77 | GetLatestAcquisitions | ||||
| 78 | |||||
| 79 | CartToShelf | ||||
| 80 | ShelfToCart | ||||
| 81 | |||||
| 82 | GetAnalyticsCount | ||||
| 83 | GetItemHolds | ||||
| 84 | |||||
| 85 | SearchItems | ||||
| 86 | |||||
| 87 | PrepareItemrecordDisplay | ||||
| 88 | |||||
| 89 | ); | ||||
| 90 | 1 | 9.62ms | 1 | 22µs | } # spent 22µs making 1 call to C4::Items::BEGIN@38 |
| 91 | |||||
| 92 | =head1 NAME | ||||
| 93 | |||||
| - - | |||||
| 133 | =head2 GetItem | ||||
| 134 | |||||
| - - | |||||
| 143 | sub GetItem { | ||||
| 144 | my ($itemnumber,$barcode, $serial) = @_; | ||||
| 145 | my $dbh = C4::Context->dbh; | ||||
| 146 | my $data; | ||||
| 147 | if ($itemnumber) { | ||||
| 148 | my $sth = $dbh->prepare(" | ||||
| 149 | SELECT * FROM items | ||||
| 150 | WHERE itemnumber = ?"); | ||||
| 151 | $sth->execute($itemnumber); | ||||
| 152 | $data = $sth->fetchrow_hashref; | ||||
| 153 | } else { | ||||
| 154 | my $sth = $dbh->prepare(" | ||||
| 155 | SELECT * FROM items | ||||
| 156 | WHERE barcode = ?" | ||||
| 157 | ); | ||||
| 158 | $sth->execute($barcode); | ||||
| 159 | $data = $sth->fetchrow_hashref; | ||||
| 160 | } | ||||
| 161 | if ( $serial) { | ||||
| 162 | my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?"); | ||||
| 163 | $ssth->execute($data->{'itemnumber'}) ; | ||||
| 164 | ($data->{'serialseq'} , $data->{'publisheddate'}) = $ssth->fetchrow_array(); | ||||
| 165 | } | ||||
| 166 | #if we don't have an items.itype, use biblioitems.itemtype. | ||||
| 167 | if( ! $data->{'itype'} ) { | ||||
| 168 | my $sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?"); | ||||
| 169 | $sth->execute($data->{'biblionumber'}); | ||||
| 170 | ($data->{'itype'}) = $sth->fetchrow_array; | ||||
| 171 | } | ||||
| 172 | return $data; | ||||
| 173 | } # sub GetItem | ||||
| 174 | |||||
| 175 | =head2 CartToShelf | ||||
| 176 | |||||
| - - | |||||
| 187 | sub CartToShelf { | ||||
| 188 | my ( $itemnumber ) = @_; | ||||
| 189 | |||||
| 190 | unless ( $itemnumber ) { | ||||
| 191 | croak "FAILED CartToShelf() - no itemnumber supplied"; | ||||
| 192 | } | ||||
| 193 | |||||
| 194 | my $item = GetItem($itemnumber); | ||||
| 195 | if ( $item->{location} eq 'CART' ) { | ||||
| 196 | $item->{location} = $item->{permanent_location}; | ||||
| 197 | ModItem($item, undef, $itemnumber); | ||||
| 198 | } | ||||
| 199 | } | ||||
| 200 | |||||
| 201 | =head2 ShelfToCart | ||||
| 202 | |||||
| - - | |||||
| 210 | sub ShelfToCart { | ||||
| 211 | my ( $itemnumber ) = @_; | ||||
| 212 | |||||
| 213 | unless ( $itemnumber ) { | ||||
| 214 | croak "FAILED ShelfToCart() - no itemnumber supplied"; | ||||
| 215 | } | ||||
| 216 | |||||
| 217 | my $item = GetItem($itemnumber); | ||||
| 218 | $item->{'location'} = 'CART'; | ||||
| 219 | ModItem($item, undef, $itemnumber); | ||||
| 220 | } | ||||
| 221 | |||||
| 222 | =head2 AddItemFromMarc | ||||
| 223 | |||||
| - - | |||||
| 232 | sub AddItemFromMarc { | ||||
| 233 | my ( $source_item_marc, $biblionumber ) = @_; | ||||
| 234 | my $dbh = C4::Context->dbh; | ||||
| 235 | |||||
| 236 | # parse item hash from MARC | ||||
| 237 | my $frameworkcode = GetFrameworkCode( $biblionumber ); | ||||
| 238 | my ($itemtag,$itemsubfield)=GetMarcFromKohaField("items.itemnumber",$frameworkcode); | ||||
| 239 | |||||
| 240 | my $localitemmarc=MARC::Record->new; | ||||
| 241 | $localitemmarc->append_fields($source_item_marc->field($itemtag)); | ||||
| 242 | my $item = &TransformMarcToKoha( $dbh, $localitemmarc, $frameworkcode ,'items'); | ||||
| 243 | my $unlinked_item_subfields = _get_unlinked_item_subfields($localitemmarc, $frameworkcode); | ||||
| 244 | return AddItem($item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields); | ||||
| 245 | } | ||||
| 246 | |||||
| 247 | =head2 AddItem | ||||
| 248 | |||||
| - - | |||||
| 268 | sub AddItem { | ||||
| 269 | my $item = shift; | ||||
| 270 | my $biblionumber = shift; | ||||
| 271 | |||||
| 272 | my $dbh = @_ ? shift : C4::Context->dbh; | ||||
| 273 | my $frameworkcode = @_ ? shift : GetFrameworkCode( $biblionumber ); | ||||
| 274 | my $unlinked_item_subfields; | ||||
| 275 | if (@_) { | ||||
| 276 | $unlinked_item_subfields = shift | ||||
| 277 | }; | ||||
| 278 | |||||
| 279 | # needs old biblionumber and biblioitemnumber | ||||
| 280 | $item->{'biblionumber'} = $biblionumber; | ||||
| 281 | my $sth = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=?"); | ||||
| 282 | $sth->execute( $item->{'biblionumber'} ); | ||||
| 283 | ($item->{'biblioitemnumber'}) = $sth->fetchrow; | ||||
| 284 | |||||
| 285 | _set_defaults_for_add($item); | ||||
| 286 | _set_derived_columns_for_add($item); | ||||
| 287 | $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields); | ||||
| 288 | # FIXME - checks here | ||||
| 289 | unless ( $item->{itype} ) { # default to biblioitem.itemtype if no itype | ||||
| 290 | my $itype_sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?"); | ||||
| 291 | $itype_sth->execute( $item->{'biblionumber'} ); | ||||
| 292 | ( $item->{'itype'} ) = $itype_sth->fetchrow_array; | ||||
| 293 | } | ||||
| 294 | |||||
| 295 | my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} ); | ||||
| 296 | $item->{'itemnumber'} = $itemnumber; | ||||
| 297 | |||||
| 298 | ModZebra( $item->{biblionumber}, "specialUpdate", "biblioserver" ); | ||||
| 299 | |||||
| 300 | logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog"); | ||||
| 301 | |||||
| 302 | return ($item->{biblionumber}, $item->{biblioitemnumber}, $itemnumber); | ||||
| 303 | } | ||||
| 304 | |||||
| 305 | =head2 AddItemBatchFromMarc | ||||
| 306 | |||||
| - - | |||||
| 350 | sub AddItemBatchFromMarc { | ||||
| 351 | my ($record, $biblionumber, $biblioitemnumber, $frameworkcode) = @_; | ||||
| 352 | my $error; | ||||
| 353 | my @itemnumbers = (); | ||||
| 354 | my @errors = (); | ||||
| 355 | my $dbh = C4::Context->dbh; | ||||
| 356 | |||||
| 357 | # We modify the record, so lets work on a clone so we don't change the | ||||
| 358 | # original. | ||||
| 359 | $record = $record->clone(); | ||||
| 360 | # loop through the item tags and start creating items | ||||
| 361 | my @bad_item_fields = (); | ||||
| 362 | my ($itemtag, $itemsubfield) = &GetMarcFromKohaField("items.itemnumber",''); | ||||
| 363 | my $item_sequence_num = 0; | ||||
| 364 | ITEMFIELD: foreach my $item_field ($record->field($itemtag)) { | ||||
| 365 | $item_sequence_num++; | ||||
| 366 | # we take the item field and stick it into a new | ||||
| 367 | # MARC record -- this is required so far because (FIXME) | ||||
| 368 | # TransformMarcToKoha requires a MARC::Record, not a MARC::Field | ||||
| 369 | # and there is no TransformMarcFieldToKoha | ||||
| 370 | my $temp_item_marc = MARC::Record->new(); | ||||
| 371 | $temp_item_marc->append_fields($item_field); | ||||
| 372 | |||||
| 373 | # add biblionumber and biblioitemnumber | ||||
| 374 | my $item = TransformMarcToKoha( $dbh, $temp_item_marc, $frameworkcode, 'items' ); | ||||
| 375 | my $unlinked_item_subfields = _get_unlinked_item_subfields($temp_item_marc, $frameworkcode); | ||||
| 376 | $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields); | ||||
| 377 | $item->{'biblionumber'} = $biblionumber; | ||||
| 378 | $item->{'biblioitemnumber'} = $biblioitemnumber; | ||||
| 379 | |||||
| 380 | # check for duplicate barcode | ||||
| 381 | my %item_errors = CheckItemPreSave($item); | ||||
| 382 | if (%item_errors) { | ||||
| 383 | push @errors, _repack_item_errors($item_sequence_num, $item, \%item_errors); | ||||
| 384 | push @bad_item_fields, $item_field; | ||||
| 385 | next ITEMFIELD; | ||||
| 386 | } | ||||
| 387 | |||||
| 388 | _set_defaults_for_add($item); | ||||
| 389 | _set_derived_columns_for_add($item); | ||||
| 390 | my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} ); | ||||
| 391 | warn $error if $error; | ||||
| 392 | push @itemnumbers, $itemnumber; # FIXME not checking error | ||||
| 393 | $item->{'itemnumber'} = $itemnumber; | ||||
| 394 | |||||
| 395 | logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog"); | ||||
| 396 | |||||
| 397 | my $new_item_marc = _marc_from_item_hash($item, $frameworkcode, $unlinked_item_subfields); | ||||
| 398 | $item_field->replace_with($new_item_marc->field($itemtag)); | ||||
| 399 | } | ||||
| 400 | |||||
| 401 | # remove any MARC item fields for rejected items | ||||
| 402 | foreach my $item_field (@bad_item_fields) { | ||||
| 403 | $record->delete_field($item_field); | ||||
| 404 | } | ||||
| 405 | |||||
| 406 | # update the MARC biblio | ||||
| 407 | # $biblionumber = ModBiblioMarc( $record, $biblionumber, $frameworkcode ); | ||||
| 408 | |||||
| 409 | return (\@itemnumbers, \@errors); | ||||
| 410 | } | ||||
| 411 | |||||
| 412 | =head2 ModItemFromMarc | ||||
| 413 | |||||
| - - | |||||
| 438 | 1 | 31µs | my %default_values_for_mod_from_marc = ( | ||
| 439 | barcode => undef, | ||||
| 440 | booksellerid => undef, | ||||
| 441 | ccode => undef, | ||||
| 442 | 'items.cn_source' => undef, | ||||
| 443 | coded_location_qualifier => undef, | ||||
| 444 | copynumber => undef, | ||||
| 445 | damaged => 0, | ||||
| 446 | # dateaccessioned => undef, | ||||
| 447 | enumchron => undef, | ||||
| 448 | holdingbranch => undef, | ||||
| 449 | homebranch => undef, | ||||
| 450 | itemcallnumber => undef, | ||||
| 451 | itemlost => 0, | ||||
| 452 | itemnotes => undef, | ||||
| 453 | itype => undef, | ||||
| 454 | location => undef, | ||||
| 455 | permanent_location => undef, | ||||
| 456 | materials => undef, | ||||
| 457 | notforloan => 0, | ||||
| 458 | paidfor => undef, | ||||
| 459 | price => undef, | ||||
| 460 | replacementprice => undef, | ||||
| 461 | replacementpricedate => undef, | ||||
| 462 | restricted => undef, | ||||
| 463 | stack => undef, | ||||
| 464 | stocknumber => undef, | ||||
| 465 | uri => undef, | ||||
| 466 | wthdrawn => 0, | ||||
| 467 | ); | ||||
| 468 | |||||
| 469 | sub ModItemFromMarc { | ||||
| 470 | my $item_marc = shift; | ||||
| 471 | my $biblionumber = shift; | ||||
| 472 | my $itemnumber = shift; | ||||
| 473 | |||||
| 474 | my $dbh = C4::Context->dbh; | ||||
| 475 | my $frameworkcode = GetFrameworkCode($biblionumber); | ||||
| 476 | my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode ); | ||||
| 477 | |||||
| 478 | my $localitemmarc = MARC::Record->new; | ||||
| 479 | $localitemmarc->append_fields( $item_marc->field($itemtag) ); | ||||
| 480 | my $item = &TransformMarcToKoha( $dbh, $localitemmarc, $frameworkcode, 'items' ); | ||||
| 481 | foreach my $item_field ( keys %default_values_for_mod_from_marc ) { | ||||
| 482 | $item->{$item_field} = $default_values_for_mod_from_marc{$item_field} unless (exists $item->{$item_field}); | ||||
| 483 | } | ||||
| 484 | my $unlinked_item_subfields = _get_unlinked_item_subfields( $localitemmarc, $frameworkcode ); | ||||
| 485 | |||||
| 486 | ModItem($item, $biblionumber, $itemnumber, $dbh, $frameworkcode, $unlinked_item_subfields); | ||||
| 487 | return $item; | ||||
| 488 | } | ||||
| 489 | |||||
| 490 | =head2 ModItem | ||||
| 491 | |||||
| - - | |||||
| 515 | sub ModItem { | ||||
| 516 | my $item = shift; | ||||
| 517 | my $biblionumber = shift; | ||||
| 518 | my $itemnumber = shift; | ||||
| 519 | |||||
| 520 | # if $biblionumber is undefined, get it from the current item | ||||
| 521 | unless (defined $biblionumber) { | ||||
| 522 | $biblionumber = _get_single_item_column('biblionumber', $itemnumber); | ||||
| 523 | } | ||||
| 524 | |||||
| 525 | my $dbh = @_ ? shift : C4::Context->dbh; | ||||
| 526 | my $frameworkcode = @_ ? shift : GetFrameworkCode( $biblionumber ); | ||||
| 527 | |||||
| 528 | my $unlinked_item_subfields; | ||||
| 529 | if (@_) { | ||||
| 530 | $unlinked_item_subfields = shift; | ||||
| 531 | $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields); | ||||
| 532 | }; | ||||
| 533 | |||||
| 534 | $item->{'itemnumber'} = $itemnumber or return; | ||||
| 535 | |||||
| 536 | $item->{onloan} = undef if $item->{itemlost}; | ||||
| 537 | |||||
| 538 | _set_derived_columns_for_mod($item); | ||||
| 539 | _do_column_fixes_for_mod($item); | ||||
| 540 | # FIXME add checks | ||||
| 541 | # duplicate barcode | ||||
| 542 | # attempt to change itemnumber | ||||
| 543 | # attempt to change biblionumber (if we want | ||||
| 544 | # an API to relink an item to a different bib, | ||||
| 545 | # it should be a separate function) | ||||
| 546 | |||||
| 547 | # update items table | ||||
| 548 | _koha_modify_item($item); | ||||
| 549 | |||||
| 550 | # request that bib be reindexed so that searching on current | ||||
| 551 | # item status is possible | ||||
| 552 | ModZebra( $biblionumber, "specialUpdate", "biblioserver" ); | ||||
| 553 | |||||
| 554 | logaction("CATALOGUING", "MODIFY", $itemnumber, Dumper($item)) if C4::Context->preference("CataloguingLog"); | ||||
| 555 | } | ||||
| 556 | |||||
| 557 | =head2 ModItemTransfer | ||||
| 558 | |||||
| - - | |||||
| 566 | sub ModItemTransfer { | ||||
| 567 | my ( $itemnumber, $frombranch, $tobranch ) = @_; | ||||
| 568 | |||||
| 569 | my $dbh = C4::Context->dbh; | ||||
| 570 | |||||
| 571 | # Remove the 'shelving cart' location status if it is being used. | ||||
| 572 | CartToShelf( $itemnumber ) if ( C4::Context->preference("ReturnToShelvingCart") ); | ||||
| 573 | |||||
| 574 | #new entry in branchtransfers.... | ||||
| 575 | my $sth = $dbh->prepare( | ||||
| 576 | "INSERT INTO branchtransfers (itemnumber, frombranch, datesent, tobranch) | ||||
| 577 | VALUES (?, ?, NOW(), ?)"); | ||||
| 578 | $sth->execute($itemnumber, $frombranch, $tobranch); | ||||
| 579 | |||||
| 580 | ModItem({ holdingbranch => $tobranch }, undef, $itemnumber); | ||||
| 581 | ModDateLastSeen($itemnumber); | ||||
| 582 | return; | ||||
| 583 | } | ||||
| 584 | |||||
| 585 | =head2 ModDateLastSeen | ||||
| 586 | |||||
| - - | |||||
| 594 | sub ModDateLastSeen { | ||||
| 595 | my ($itemnumber) = @_; | ||||
| 596 | |||||
| 597 | my $today = C4::Dates->new(); | ||||
| 598 | ModItem({ itemlost => 0, datelastseen => $today->output("iso") }, undef, $itemnumber); | ||||
| 599 | } | ||||
| 600 | |||||
| 601 | =head2 DelItem | ||||
| 602 | |||||
| - - | |||||
| 609 | sub DelItem { | ||||
| 610 | my ( $dbh, $biblionumber, $itemnumber ) = @_; | ||||
| 611 | |||||
| 612 | # FIXME check the item has no current issues | ||||
| 613 | |||||
| 614 | _koha_delete_item( $dbh, $itemnumber ); | ||||
| 615 | |||||
| 616 | # get the MARC record | ||||
| 617 | my $record = GetMarcBiblio($biblionumber); | ||||
| 618 | ModZebra( $biblionumber, "specialUpdate", "biblioserver" ); | ||||
| 619 | |||||
| 620 | # backup the record | ||||
| 621 | my $copy2deleted = $dbh->prepare("UPDATE deleteditems SET marc=? WHERE itemnumber=?"); | ||||
| 622 | $copy2deleted->execute( $record->as_usmarc(), $itemnumber ); | ||||
| 623 | # This last update statement makes that the timestamp column in deleteditems is updated too. If you remove these lines, please add a line to update the timestamp separately. See Bugzilla report 7146 and Biblio.pm (DelBiblio). | ||||
| 624 | |||||
| 625 | #search item field code | ||||
| 626 | logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog"); | ||||
| 627 | } | ||||
| 628 | |||||
| 629 | =head2 CheckItemPreSave | ||||
| 630 | |||||
| - - | |||||
| 671 | sub CheckItemPreSave { | ||||
| 672 | my $item_ref = shift; | ||||
| 673 | require C4::Branch; | ||||
| 674 | |||||
| 675 | my %errors = (); | ||||
| 676 | |||||
| 677 | # check for duplicate barcode | ||||
| 678 | if (exists $item_ref->{'barcode'} and defined $item_ref->{'barcode'}) { | ||||
| 679 | my $existing_itemnumber = GetItemnumberFromBarcode($item_ref->{'barcode'}); | ||||
| 680 | if ($existing_itemnumber) { | ||||
| 681 | if (!exists $item_ref->{'itemnumber'} # new item | ||||
| 682 | or $item_ref->{'itemnumber'} != $existing_itemnumber) { # existing item | ||||
| 683 | $errors{'duplicate_barcode'} = $item_ref->{'barcode'}; | ||||
| 684 | } | ||||
| 685 | } | ||||
| 686 | } | ||||
| 687 | |||||
| 688 | # check for valid home branch | ||||
| 689 | if (exists $item_ref->{'homebranch'} and defined $item_ref->{'homebranch'}) { | ||||
| 690 | my $branch_name = C4::Branch::GetBranchName($item_ref->{'homebranch'}); | ||||
| 691 | unless (defined $branch_name) { | ||||
| 692 | # relies on fact that branches.branchname is a non-NULL column, | ||||
| 693 | # so GetBranchName returns undef only if branch does not exist | ||||
| 694 | $errors{'invalid_homebranch'} = $item_ref->{'homebranch'}; | ||||
| 695 | } | ||||
| 696 | } | ||||
| 697 | |||||
| 698 | # check for valid holding branch | ||||
| 699 | if (exists $item_ref->{'holdingbranch'} and defined $item_ref->{'holdingbranch'}) { | ||||
| 700 | my $branch_name = C4::Branch::GetBranchName($item_ref->{'holdingbranch'}); | ||||
| 701 | unless (defined $branch_name) { | ||||
| 702 | # relies on fact that branches.branchname is a non-NULL column, | ||||
| 703 | # so GetBranchName returns undef only if branch does not exist | ||||
| 704 | $errors{'invalid_holdingbranch'} = $item_ref->{'holdingbranch'}; | ||||
| 705 | } | ||||
| 706 | } | ||||
| 707 | |||||
| 708 | return %errors; | ||||
| 709 | |||||
| 710 | } | ||||
| 711 | |||||
| 712 | =head1 EXPORTED SPECIAL ACCESSOR FUNCTIONS | ||||
| 713 | |||||
| - - | |||||
| 725 | =head2 GetItemStatus | ||||
| 726 | |||||
| - - | |||||
| 763 | sub GetItemStatus { | ||||
| 764 | |||||
| 765 | # returns a reference to a hash of references to status... | ||||
| 766 | my ($fwk) = @_; | ||||
| 767 | my %itemstatus; | ||||
| 768 | my $dbh = C4::Context->dbh; | ||||
| 769 | my $sth; | ||||
| 770 | $fwk = '' unless ($fwk); | ||||
| 771 | my ( $tag, $subfield ) = | ||||
| 772 | GetMarcFromKohaField( "items.notforloan", $fwk ); | ||||
| 773 | if ( $tag and $subfield ) { | ||||
| 774 | my $sth = | ||||
| 775 | $dbh->prepare( | ||||
| 776 | "SELECT authorised_value | ||||
| 777 | FROM marc_subfield_structure | ||||
| 778 | WHERE tagfield=? | ||||
| 779 | AND tagsubfield=? | ||||
| 780 | AND frameworkcode=? | ||||
| 781 | " | ||||
| 782 | ); | ||||
| 783 | $sth->execute( $tag, $subfield, $fwk ); | ||||
| 784 | if ( my ($authorisedvaluecat) = $sth->fetchrow ) { | ||||
| 785 | my $authvalsth = | ||||
| 786 | $dbh->prepare( | ||||
| 787 | "SELECT authorised_value,lib | ||||
| 788 | FROM authorised_values | ||||
| 789 | WHERE category=? | ||||
| 790 | ORDER BY lib | ||||
| 791 | " | ||||
| 792 | ); | ||||
| 793 | $authvalsth->execute($authorisedvaluecat); | ||||
| 794 | while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { | ||||
| 795 | $itemstatus{$authorisedvalue} = $lib; | ||||
| 796 | } | ||||
| 797 | return \%itemstatus; | ||||
| 798 | exit 1; | ||||
| 799 | } | ||||
| 800 | else { | ||||
| 801 | |||||
| 802 | #No authvalue list | ||||
| 803 | # build default | ||||
| 804 | } | ||||
| 805 | } | ||||
| 806 | |||||
| 807 | #No authvalue list | ||||
| 808 | #build default | ||||
| 809 | $itemstatus{"1"} = "Not For Loan"; | ||||
| 810 | return \%itemstatus; | ||||
| 811 | } | ||||
| 812 | |||||
| 813 | =head2 GetItemLocation | ||||
| 814 | |||||
| - - | |||||
| 851 | sub GetItemLocation { | ||||
| 852 | |||||
| 853 | # returns a reference to a hash of references to location... | ||||
| 854 | my ($fwk) = @_; | ||||
| 855 | my %itemlocation; | ||||
| 856 | my $dbh = C4::Context->dbh; | ||||
| 857 | my $sth; | ||||
| 858 | $fwk = '' unless ($fwk); | ||||
| 859 | my ( $tag, $subfield ) = | ||||
| 860 | GetMarcFromKohaField( "items.location", $fwk ); | ||||
| 861 | if ( $tag and $subfield ) { | ||||
| 862 | my $sth = | ||||
| 863 | $dbh->prepare( | ||||
| 864 | "SELECT authorised_value | ||||
| 865 | FROM marc_subfield_structure | ||||
| 866 | WHERE tagfield=? | ||||
| 867 | AND tagsubfield=? | ||||
| 868 | AND frameworkcode=?" | ||||
| 869 | ); | ||||
| 870 | $sth->execute( $tag, $subfield, $fwk ); | ||||
| 871 | if ( my ($authorisedvaluecat) = $sth->fetchrow ) { | ||||
| 872 | my $authvalsth = | ||||
| 873 | $dbh->prepare( | ||||
| 874 | "SELECT authorised_value,lib | ||||
| 875 | FROM authorised_values | ||||
| 876 | WHERE category=? | ||||
| 877 | ORDER BY lib" | ||||
| 878 | ); | ||||
| 879 | $authvalsth->execute($authorisedvaluecat); | ||||
| 880 | while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { | ||||
| 881 | $itemlocation{$authorisedvalue} = $lib; | ||||
| 882 | } | ||||
| 883 | return \%itemlocation; | ||||
| 884 | exit 1; | ||||
| 885 | } | ||||
| 886 | else { | ||||
| 887 | |||||
| 888 | #No authvalue list | ||||
| 889 | # build default | ||||
| 890 | } | ||||
| 891 | } | ||||
| 892 | |||||
| 893 | #No authvalue list | ||||
| 894 | #build default | ||||
| 895 | $itemlocation{"1"} = "Not For Loan"; | ||||
| 896 | return \%itemlocation; | ||||
| 897 | } | ||||
| 898 | |||||
| 899 | =head2 GetLostItems | ||||
| 900 | |||||
| - - | |||||
| 933 | sub GetLostItems { | ||||
| 934 | # Getting input args. | ||||
| 935 | my $where = shift; | ||||
| 936 | my $orderby = shift; | ||||
| 937 | my $dbh = C4::Context->dbh; | ||||
| 938 | |||||
| 939 | my $query = " | ||||
| 940 | SELECT title, author, lib, itemlost, authorised_value, barcode, datelastseen, price, replacementprice, homebranch, | ||||
| 941 | itype, itemtype, holdingbranch, location, itemnotes, items.biblionumber as biblionumber | ||||
| 942 | FROM items | ||||
| 943 | LEFT JOIN biblio ON (items.biblionumber = biblio.biblionumber) | ||||
| 944 | LEFT JOIN biblioitems ON (items.biblionumber = biblioitems.biblionumber) | ||||
| 945 | LEFT JOIN authorised_values ON (items.itemlost = authorised_values.authorised_value) | ||||
| 946 | WHERE | ||||
| 947 | authorised_values.category = 'LOST' | ||||
| 948 | AND itemlost IS NOT NULL | ||||
| 949 | AND itemlost <> 0 | ||||
| 950 | "; | ||||
| 951 | my @query_parameters; | ||||
| 952 | foreach my $key (keys %$where) { | ||||
| 953 | $query .= " AND $key LIKE ?"; | ||||
| 954 | push @query_parameters, "%$where->{$key}%"; | ||||
| 955 | } | ||||
| 956 | my @ordervalues = qw/title author homebranch itype barcode price replacementprice lib datelastseen location/; | ||||
| 957 | |||||
| 958 | if ( defined $orderby && grep($orderby, @ordervalues)) { | ||||
| 959 | $query .= ' ORDER BY '.$orderby; | ||||
| 960 | } | ||||
| 961 | |||||
| 962 | my $sth = $dbh->prepare($query); | ||||
| 963 | $sth->execute( @query_parameters ); | ||||
| 964 | my $items = []; | ||||
| 965 | while ( my $row = $sth->fetchrow_hashref ){ | ||||
| 966 | push @$items, $row; | ||||
| 967 | } | ||||
| 968 | return $items; | ||||
| 969 | } | ||||
| 970 | |||||
| 971 | =head2 GetItemsForInventory | ||||
| 972 | |||||
| - - | |||||
| 990 | sub GetItemsForInventory { | ||||
| 991 | my ( $minlocation, $maxlocation,$location, $itemtype, $ignoreissued, $datelastseen, $branchcode, $branch, $offset, $size, $statushash ) = @_; | ||||
| 992 | my $dbh = C4::Context->dbh; | ||||
| 993 | my ( @bind_params, @where_strings ); | ||||
| 994 | |||||
| 995 | my $query = <<'END_SQL'; | ||||
| 996 | SELECT items.itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, datelastseen | ||||
| 997 | FROM items | ||||
| 998 | LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber | ||||
| 999 | LEFT JOIN biblioitems on items.biblionumber = biblioitems.biblionumber | ||||
| 1000 | END_SQL | ||||
| 1001 | if ($statushash){ | ||||
| 1002 | for my $authvfield (keys %$statushash){ | ||||
| 1003 | if ( scalar @{$statushash->{$authvfield}} > 0 ){ | ||||
| 1004 | my $joinedvals = join ',', @{$statushash->{$authvfield}}; | ||||
| 1005 | push @where_strings, "$authvfield in (" . $joinedvals . ")"; | ||||
| 1006 | } | ||||
| 1007 | } | ||||
| 1008 | } | ||||
| 1009 | |||||
| 1010 | if ($minlocation) { | ||||
| 1011 | push @where_strings, 'itemcallnumber >= ?'; | ||||
| 1012 | push @bind_params, $minlocation; | ||||
| 1013 | } | ||||
| 1014 | |||||
| 1015 | if ($maxlocation) { | ||||
| 1016 | push @where_strings, 'itemcallnumber <= ?'; | ||||
| 1017 | push @bind_params, $maxlocation; | ||||
| 1018 | } | ||||
| 1019 | |||||
| 1020 | if ($datelastseen) { | ||||
| 1021 | $datelastseen = format_date_in_iso($datelastseen); | ||||
| 1022 | push @where_strings, '(datelastseen < ? OR datelastseen IS NULL)'; | ||||
| 1023 | push @bind_params, $datelastseen; | ||||
| 1024 | } | ||||
| 1025 | |||||
| 1026 | if ( $location ) { | ||||
| 1027 | push @where_strings, 'items.location = ?'; | ||||
| 1028 | push @bind_params, $location; | ||||
| 1029 | } | ||||
| 1030 | |||||
| 1031 | if ( $branchcode ) { | ||||
| 1032 | if($branch eq "homebranch"){ | ||||
| 1033 | push @where_strings, 'items.homebranch = ?'; | ||||
| 1034 | }else{ | ||||
| 1035 | push @where_strings, 'items.holdingbranch = ?'; | ||||
| 1036 | } | ||||
| 1037 | push @bind_params, $branchcode; | ||||
| 1038 | } | ||||
| 1039 | |||||
| 1040 | if ( $itemtype ) { | ||||
| 1041 | push @where_strings, 'biblioitems.itemtype = ?'; | ||||
| 1042 | push @bind_params, $itemtype; | ||||
| 1043 | } | ||||
| 1044 | |||||
| 1045 | if ( $ignoreissued) { | ||||
| 1046 | $query .= "LEFT JOIN issues ON items.itemnumber = issues.itemnumber "; | ||||
| 1047 | push @where_strings, 'issues.date_due IS NULL'; | ||||
| 1048 | } | ||||
| 1049 | |||||
| 1050 | if ( @where_strings ) { | ||||
| 1051 | $query .= 'WHERE '; | ||||
| 1052 | $query .= join ' AND ', @where_strings; | ||||
| 1053 | } | ||||
| 1054 | $query .= ' ORDER BY items.cn_sort, itemcallnumber, title'; | ||||
| 1055 | my $sth = $dbh->prepare($query); | ||||
| 1056 | $sth->execute( @bind_params ); | ||||
| 1057 | |||||
| 1058 | my @results; | ||||
| 1059 | $size--; | ||||
| 1060 | while ( my $row = $sth->fetchrow_hashref ) { | ||||
| 1061 | $offset-- if ($offset); | ||||
| 1062 | $row->{datelastseen}=format_date($row->{datelastseen}); | ||||
| 1063 | if ( ( !$offset ) && $size ) { | ||||
| 1064 | push @results, $row; | ||||
| 1065 | $size--; | ||||
| 1066 | } | ||||
| 1067 | } | ||||
| 1068 | return \@results; | ||||
| 1069 | } | ||||
| 1070 | |||||
| 1071 | =head2 GetItemsCount | ||||
| 1072 | |||||
| - - | |||||
| 1079 | sub GetItemsCount { | ||||
| 1080 | my ( $biblionumber ) = @_; | ||||
| 1081 | my $dbh = C4::Context->dbh; | ||||
| 1082 | my $query = "SELECT count(*) | ||||
| 1083 | FROM items | ||||
| 1084 | WHERE biblionumber=?"; | ||||
| 1085 | my $sth = $dbh->prepare($query); | ||||
| 1086 | $sth->execute($biblionumber); | ||||
| 1087 | my $count = $sth->fetchrow; | ||||
| 1088 | return ($count); | ||||
| 1089 | } | ||||
| 1090 | |||||
| 1091 | =head2 GetItemInfosOf | ||||
| 1092 | |||||
| - - | |||||
| 1097 | sub GetItemInfosOf { | ||||
| 1098 | my @itemnumbers = @_; | ||||
| 1099 | |||||
| 1100 | my $query = ' | ||||
| 1101 | SELECT * | ||||
| 1102 | FROM items | ||||
| 1103 | WHERE itemnumber IN (' . join( ',', @itemnumbers ) . ') | ||||
| 1104 | '; | ||||
| 1105 | return get_infos_of( $query, 'itemnumber' ); | ||||
| 1106 | } | ||||
| 1107 | |||||
| 1108 | =head2 GetItemsByBiblioitemnumber | ||||
| 1109 | |||||
| - - | |||||
| 1117 | sub GetItemsByBiblioitemnumber { | ||||
| 1118 | my ( $bibitem ) = @_; | ||||
| 1119 | my $dbh = C4::Context->dbh; | ||||
| 1120 | my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ?") || die $dbh->errstr; | ||||
| 1121 | # Get all items attached to a biblioitem | ||||
| 1122 | my $i = 0; | ||||
| 1123 | my @results; | ||||
| 1124 | $sth->execute($bibitem) || die $sth->errstr; | ||||
| 1125 | while ( my $data = $sth->fetchrow_hashref ) { | ||||
| 1126 | # Foreach item, get circulation information | ||||
| 1127 | my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers | ||||
| 1128 | WHERE itemnumber = ? | ||||
| 1129 | AND issues.borrowernumber = borrowers.borrowernumber" | ||||
| 1130 | ); | ||||
| 1131 | $sth2->execute( $data->{'itemnumber'} ); | ||||
| 1132 | if ( my $data2 = $sth2->fetchrow_hashref ) { | ||||
| 1133 | # if item is out, set the due date and who it is out too | ||||
| 1134 | $data->{'date_due'} = $data2->{'date_due'}; | ||||
| 1135 | $data->{'cardnumber'} = $data2->{'cardnumber'}; | ||||
| 1136 | $data->{'borrowernumber'} = $data2->{'borrowernumber'}; | ||||
| 1137 | } | ||||
| 1138 | else { | ||||
| 1139 | # set date_due to blank, so in the template we check itemlost, and wthdrawn | ||||
| 1140 | $data->{'date_due'} = ''; | ||||
| 1141 | } # else | ||||
| 1142 | # Find the last 3 people who borrowed this item. | ||||
| 1143 | my $query2 = "SELECT * FROM old_issues, borrowers WHERE itemnumber = ? | ||||
| 1144 | AND old_issues.borrowernumber = borrowers.borrowernumber | ||||
| 1145 | ORDER BY returndate desc,timestamp desc LIMIT 3"; | ||||
| 1146 | $sth2 = $dbh->prepare($query2) || die $dbh->errstr; | ||||
| 1147 | $sth2->execute( $data->{'itemnumber'} ) || die $sth2->errstr; | ||||
| 1148 | my $i2 = 0; | ||||
| 1149 | while ( my $data2 = $sth2->fetchrow_hashref ) { | ||||
| 1150 | $data->{"timestamp$i2"} = $data2->{'timestamp'}; | ||||
| 1151 | $data->{"card$i2"} = $data2->{'cardnumber'}; | ||||
| 1152 | $data->{"borrower$i2"} = $data2->{'borrowernumber'}; | ||||
| 1153 | $i2++; | ||||
| 1154 | } | ||||
| 1155 | push(@results,$data); | ||||
| 1156 | } | ||||
| 1157 | return (\@results); | ||||
| 1158 | } | ||||
| 1159 | |||||
| 1160 | =head2 GetItemsInfo | ||||
| 1161 | |||||
| - - | |||||
| 1202 | # spent 832ms (12.4+819) within C4::Items::GetItemsInfo which was called 25 times, avg 33.3ms/call:
# 25 times (12.4ms+819ms) by C4::XSLT::buildKohaItemsNamespace at line 248 of /usr/share/koha/lib/C4/XSLT.pm, avg 33.3ms/call | ||||
| 1203 | 325 | 83.8ms | my ( $biblionumber ) = @_; | ||
| 1204 | 25 | 24.4ms | my $dbh = C4::Context->dbh; # spent 24.4ms making 25 calls to C4::Context::dbh, avg 978µs/call | ||
| 1205 | # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance. | ||||
| 1206 | 25 | 262µs | my $query = " # spent 262µs making 25 calls to C4::Context::preference, avg 10µs/call | ||
| 1207 | SELECT items.*, | ||||
| 1208 | biblio.*, | ||||
| 1209 | biblioitems.volume, | ||||
| 1210 | biblioitems.number, | ||||
| 1211 | biblioitems.itemtype, | ||||
| 1212 | biblioitems.isbn, | ||||
| 1213 | biblioitems.issn, | ||||
| 1214 | biblioitems.publicationyear, | ||||
| 1215 | biblioitems.publishercode, | ||||
| 1216 | biblioitems.volumedate, | ||||
| 1217 | biblioitems.volumedesc, | ||||
| 1218 | biblioitems.lccn, | ||||
| 1219 | biblioitems.url, | ||||
| 1220 | items.notforloan as itemnotforloan, | ||||
| 1221 | itemtypes.description, | ||||
| 1222 | itemtypes.notforloan as notforloan_per_itemtype, | ||||
| 1223 | holding.branchurl, | ||||
| 1224 | holding.branchname, | ||||
| 1225 | holding.opac_info as branch_opac_info | ||||
| 1226 | FROM items | ||||
| 1227 | LEFT JOIN branches AS holding ON items.holdingbranch = holding.branchcode | ||||
| 1228 | LEFT JOIN branches AS home ON items.homebranch=home.branchcode | ||||
| 1229 | LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber | ||||
| 1230 | LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber | ||||
| 1231 | LEFT JOIN itemtypes ON itemtypes.itemtype = " | ||||
| 1232 | . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype'); | ||||
| 1233 | $query .= " WHERE items.biblionumber = ? ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ; | ||||
| 1234 | 1 | 210µs | 50 | 6.07ms | my $sth = $dbh->prepare($query); # spent 3.22ms making 25 calls to DBI::db::prepare, avg 129µs/call
# spent 2.85ms making 25 calls to DBD::mysql::db::prepare, avg 114µs/call |
| 1235 | 25 | 74.6ms | $sth->execute($biblionumber); # spent 74.6ms making 25 calls to DBI::st::execute, avg 2.98ms/call | ||
| 1236 | my $i = 0; | ||||
| 1237 | my @results; | ||||
| 1238 | my $serial; | ||||
| 1239 | |||||
| 1240 | 1 | 158µs | 50 | 5.72ms | my $isth = $dbh->prepare( # spent 3.11ms making 25 calls to DBI::db::prepare, avg 124µs/call
# spent 2.62ms making 25 calls to DBD::mysql::db::prepare, avg 105µs/call |
| 1241 | "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode | ||||
| 1242 | FROM issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber | ||||
| 1243 | WHERE itemnumber = ?" | ||||
| 1244 | ); | ||||
| 1245 | 1 | 158µs | 50 | 3.06ms | my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=? "); # spent 1.69ms making 25 calls to DBI::db::prepare, avg 67µs/call
# spent 1.37ms making 25 calls to DBD::mysql::db::prepare, avg 55µs/call |
| 1246 | 672 | 183ms | 459 | 10.6ms | while ( my $data = $sth->fetchrow_hashref ) { # spent 6.37ms making 57 calls to DBI::st::fetchrow_hashref, avg 112µs/call
# spent 1.47ms making 192 calls to DBI::common::DESTROY, avg 8µs/call
# spent 1.35ms making 57 calls to DBI::common::FETCH, avg 24µs/call
# spent 1.08ms making 57 calls to DBI::st::fetch, avg 19µs/call
# spent 332µs making 96 calls to DBD::_mem::common::DESTROY, avg 3µs/call |
| 1247 | my $datedue = ''; | ||||
| 1248 | 32 | 42.8ms | $isth->execute( $data->{'itemnumber'} ); # spent 42.8ms making 32 calls to DBI::st::execute, avg 1.34ms/call | ||
| 1249 | 96 | 2.63ms | if ( my $idata = $isth->fetchrow_hashref ) { # spent 1.72ms making 32 calls to DBI::st::fetchrow_hashref, avg 54µs/call
# spent 626µs making 32 calls to DBI::common::FETCH, avg 20µs/call
# spent 280µs making 32 calls to DBI::st::fetch, avg 9µs/call | ||
| 1250 | $data->{borrowernumber} = $idata->{borrowernumber}; | ||||
| 1251 | $data->{cardnumber} = $idata->{cardnumber}; | ||||
| 1252 | $data->{surname} = $idata->{surname}; | ||||
| 1253 | $data->{firstname} = $idata->{firstname}; | ||||
| 1254 | $data->{lastreneweddate} = $idata->{lastreneweddate}; | ||||
| 1255 | $datedue = $idata->{'date_due'}; | ||||
| 1256 | if (C4::Context->preference("IndependantBranches")){ | ||||
| 1257 | my $userenv = C4::Context->userenv; | ||||
| 1258 | if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { | ||||
| 1259 | $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch}); | ||||
| 1260 | } | ||||
| 1261 | } | ||||
| 1262 | } | ||||
| 1263 | if ( $data->{'serial'}) { | ||||
| 1264 | $ssth->execute($data->{'itemnumber'}) ; | ||||
| 1265 | ($data->{'serialseq'} , $data->{'publisheddate'}) = $ssth->fetchrow_array(); | ||||
| 1266 | $serial = 1; | ||||
| 1267 | } | ||||
| 1268 | #get branch information..... | ||||
| 1269 | 1 | 212µs | 64 | 5.24ms | my $bsth = $dbh->prepare( # spent 2.79ms making 32 calls to DBI::db::prepare, avg 87µs/call
# spent 2.45ms making 32 calls to DBD::mysql::db::prepare, avg 76µs/call |
| 1270 | "SELECT * FROM branches WHERE branchcode = ? | ||||
| 1271 | " | ||||
| 1272 | ); | ||||
| 1273 | 32 | 35.3ms | $bsth->execute( $data->{'holdingbranch'} ); # spent 35.3ms making 32 calls to DBI::st::execute, avg 1.10ms/call | ||
| 1274 | 96 | 3.70ms | if ( my $bdata = $bsth->fetchrow_hashref ) { # spent 2.65ms making 32 calls to DBI::st::fetchrow_hashref, avg 83µs/call
# spent 588µs making 32 calls to DBI::common::FETCH, avg 18µs/call
# spent 455µs making 32 calls to DBI::st::fetch, avg 14µs/call | ||
| 1275 | $data->{'branchname'} = $bdata->{'branchname'}; | ||||
| 1276 | } | ||||
| 1277 | $data->{'datedue'} = $datedue; | ||||
| 1278 | |||||
| 1279 | # get notforloan complete status if applicable | ||||
| 1280 | 64 | 671µs | 128 | 64.3ms | if ( my $code = C4::Koha::GetAuthValCode( 'items.notforloan', $data->{frameworkcode} ) ) { # spent 63.6ms making 32 calls to C4::Koha::GetAuthValCode, avg 1.99ms/call
# spent 522µs making 64 calls to DBI::common::DESTROY, avg 8µs/call
# spent 126µs making 32 calls to DBD::_mem::common::DESTROY, avg 4µs/call |
| 1281 | 128 | 71.4ms | $data->{notforloanvalue} = C4::Koha::GetKohaAuthorisedValueLib( $code, $data->{itemnotforloan} ); # spent 71.0ms making 32 calls to C4::Koha::GetKohaAuthorisedValueLib, avg 2.22ms/call
# spent 296µs making 64 calls to DBI::common::DESTROY, avg 5µs/call
# spent 105µs making 32 calls to DBD::_mem::common::DESTROY, avg 3µs/call | ||
| 1282 | 128 | 69.9ms | $data->{notforloanvalueopac} = C4::Koha::GetKohaAuthorisedValueLib( $code, $data->{itemnotforloan}, 1 ); # spent 69.5ms making 32 calls to C4::Koha::GetKohaAuthorisedValueLib, avg 2.17ms/call
# spent 333µs making 64 calls to DBI::common::DESTROY, avg 5µs/call
# spent 86µs making 32 calls to DBD::_mem::common::DESTROY, avg 3µs/call | ||
| 1283 | } | ||||
| 1284 | |||||
| 1285 | # get restricted status and description if applicable | ||||
| 1286 | 64 | 573µs | 128 | 73.8ms | if ( my $code = C4::Koha::GetAuthValCode( 'items.restricted', $data->{frameworkcode} ) ) { # spent 73.1ms making 32 calls to C4::Koha::GetAuthValCode, avg 2.29ms/call
# spent 512µs making 64 calls to DBI::common::DESTROY, avg 8µs/call
# spent 114µs making 32 calls to DBD::_mem::common::DESTROY, avg 4µs/call |
| 1287 | 128 | 70.4ms | $data->{restrictedopac} = C4::Koha::GetKohaAuthorisedValueLib( $code, $data->{restricted}, 1 ); # spent 70.0ms making 32 calls to C4::Koha::GetKohaAuthorisedValueLib, avg 2.19ms/call
# spent 327µs making 64 calls to DBI::common::DESTROY, avg 5µs/call
# spent 90µs making 32 calls to DBD::_mem::common::DESTROY, avg 3µs/call | ||
| 1288 | 128 | 72.6ms | $data->{restricted} = C4::Koha::GetKohaAuthorisedValueLib( $code, $data->{restricted} ); # spent 72.2ms making 32 calls to C4::Koha::GetKohaAuthorisedValueLib, avg 2.26ms/call
# spent 366µs making 64 calls to DBI::common::DESTROY, avg 6µs/call
# spent 83µs making 32 calls to DBD::_mem::common::DESTROY, avg 3µs/call | ||
| 1289 | } | ||||
| 1290 | |||||
| 1291 | # my stack procedures | ||||
| 1292 | 188 | 102ms | if ( my $code = C4::Koha::GetAuthValCode( 'items.stack', $data->{frameworkcode} ) ) { # spent 68.9ms making 32 calls to C4::Koha::GetAuthValCode, avg 2.15ms/call
# spent 32.1ms making 15 calls to C4::Koha::GetKohaAuthorisedValueLib, avg 2.14ms/call
# spent 578µs making 94 calls to DBI::common::DESTROY, avg 6µs/call
# spent 143µs making 47 calls to DBD::_mem::common::DESTROY, avg 3µs/call | ||
| 1293 | $data->{stack} = C4::Koha::GetKohaAuthorisedValueLib( $code, $data->{stack} ); | ||||
| 1294 | } | ||||
| 1295 | |||||
| 1296 | # Get restricted value | ||||
| 1297 | |||||
| 1298 | 1 | 188µs | 64 | 4.62ms | my $restrictedstatus = $dbh->prepare( # spent 2.52ms making 32 calls to DBI::db::prepare, avg 79µs/call
# spent 2.11ms making 32 calls to DBD::mysql::db::prepare, avg 66µs/call |
| 1299 | "SELECT lib | ||||
| 1300 | FROM authorised_values | ||||
| 1301 | WHERE category=? | ||||
| 1302 | AND authorised_value=? | ||||
| 1303 | " | ||||
| 1304 | ); | ||||
| 1305 | 32 | 30.4ms | $restrictedstatus->execute( 'RESTRICTED', $data->{'restricted'}); # spent 30.4ms making 32 calls to DBI::st::execute, avg 948µs/call | ||
| 1306 | 32 | 424µs | my ($lib) = $restrictedstatus->fetchrow; # spent 424µs making 32 calls to DBI::st::fetchrow, avg 13µs/call | ||
| 1307 | $data->{restrictedvalue} = $lib; | ||||
| 1308 | # Find the last 3 people who borrowed this item. | ||||
| 1309 | 1 | 157µs | 64 | 4.36ms | my $sth2 = $dbh->prepare("SELECT * FROM old_issues,borrowers # spent 2.33ms making 32 calls to DBI::db::prepare, avg 73µs/call
# spent 2.03ms making 32 calls to DBD::mysql::db::prepare, avg 63µs/call |
| 1310 | WHERE itemnumber = ? | ||||
| 1311 | AND old_issues.borrowernumber = borrowers.borrowernumber | ||||
| 1312 | ORDER BY returndate DESC | ||||
| 1313 | LIMIT 3"); | ||||
| 1314 | 32 | 58.3ms | $sth2->execute($data->{'itemnumber'}); # spent 58.3ms making 32 calls to DBI::st::execute, avg 1.82ms/call | ||
| 1315 | my $ii = 0; | ||||
| 1316 | 96 | 4.16ms | while (my $data2 = $sth2->fetchrow_hashref()) { # spent 2.52ms making 32 calls to DBI::st::fetchrow_hashref, avg 79µs/call
# spent 1.35ms making 32 calls to DBI::common::FETCH, avg 42µs/call
# spent 291µs making 32 calls to DBI::st::fetch, avg 9µs/call | ||
| 1317 | $data->{"timestamp$ii"} = $data2->{'timestamp'} if $data2->{'timestamp'}; | ||||
| 1318 | $data->{"card$ii"} = $data2->{'cardnumber'} if $data2->{'cardnumber'}; | ||||
| 1319 | $data->{"borrower$ii"} = $data2->{'borrowernumber'} if $data2->{'borrowernumber'}; | ||||
| 1320 | $ii++; | ||||
| 1321 | } | ||||
| 1322 | |||||
| 1323 | $results[$i] = $data; | ||||
| 1324 | $i++; | ||||
| 1325 | } | ||||
| 1326 | 25 | 2.98ms | if($serial) { | ||
| 1327 | return( sort { ($b->{'publisheddate'} || $b->{'enumchron'}) cmp ($a->{'publisheddate'} || $a->{'enumchron'}) } @results ); | ||||
| 1328 | } else { | ||||
| 1329 | return (@results); | ||||
| 1330 | } | ||||
| 1331 | } | ||||
| 1332 | |||||
| 1333 | =head2 GetItemsLocationInfo | ||||
| 1334 | |||||
| - - | |||||
| 1376 | sub GetItemsLocationInfo { | ||||
| 1377 | my $biblionumber = shift; | ||||
| 1378 | my @results; | ||||
| 1379 | |||||
| 1380 | my $dbh = C4::Context->dbh; | ||||
| 1381 | my $query = "SELECT a.branchname as homebranch, b.branchname as holdingbranch, | ||||
| 1382 | location, itemcallnumber, cn_sort | ||||
| 1383 | FROM items, branches as a, branches as b | ||||
| 1384 | WHERE homebranch = a.branchcode AND holdingbranch = b.branchcode | ||||
| 1385 | AND biblionumber = ? | ||||
| 1386 | ORDER BY cn_sort ASC"; | ||||
| 1387 | my $sth = $dbh->prepare($query); | ||||
| 1388 | $sth->execute($biblionumber); | ||||
| 1389 | |||||
| 1390 | while ( my $data = $sth->fetchrow_hashref ) { | ||||
| 1391 | $data->{location_intranet} = GetKohaAuthorisedValueLib('LOC', $data->{location}); | ||||
| 1392 | $data->{location_opac}= GetKohaAuthorisedValueLib('LOC', $data->{location}, 1); | ||||
| 1393 | push @results, $data; | ||||
| 1394 | } | ||||
| 1395 | return @results; | ||||
| 1396 | } | ||||
| 1397 | |||||
| 1398 | =head2 GetHostItemsInfo | ||||
| 1399 | |||||
| - - | |||||
| 1405 | sub GetHostItemsInfo { | ||||
| 1406 | my ($record) = @_; | ||||
| 1407 | my @returnitemsInfo; | ||||
| 1408 | |||||
| 1409 | if (C4::Context->preference('marcflavour') eq 'MARC21' || | ||||
| 1410 | C4::Context->preference('marcflavour') eq 'NORMARC'){ | ||||
| 1411 | foreach my $hostfield ( $record->field('773') ) { | ||||
| 1412 | my $hostbiblionumber = $hostfield->subfield("0"); | ||||
| 1413 | my $linkeditemnumber = $hostfield->subfield("9"); | ||||
| 1414 | my @hostitemInfos = GetItemsInfo($hostbiblionumber); | ||||
| 1415 | foreach my $hostitemInfo (@hostitemInfos){ | ||||
| 1416 | if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){ | ||||
| 1417 | push (@returnitemsInfo,$hostitemInfo); | ||||
| 1418 | last; | ||||
| 1419 | } | ||||
| 1420 | } | ||||
| 1421 | } | ||||
| 1422 | } elsif ( C4::Context->preference('marcflavour') eq 'UNIMARC'){ | ||||
| 1423 | foreach my $hostfield ( $record->field('461') ) { | ||||
| 1424 | my $hostbiblionumber = $hostfield->subfield("0"); | ||||
| 1425 | my $linkeditemnumber = $hostfield->subfield("9"); | ||||
| 1426 | my @hostitemInfos = GetItemsInfo($hostbiblionumber); | ||||
| 1427 | foreach my $hostitemInfo (@hostitemInfos){ | ||||
| 1428 | if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){ | ||||
| 1429 | push (@returnitemsInfo,$hostitemInfo); | ||||
| 1430 | last; | ||||
| 1431 | } | ||||
| 1432 | } | ||||
| 1433 | } | ||||
| 1434 | } | ||||
| 1435 | return @returnitemsInfo; | ||||
| 1436 | } | ||||
| 1437 | |||||
| 1438 | |||||
| 1439 | =head2 GetLastAcquisitions | ||||
| 1440 | |||||
| - - | |||||
| 1446 | sub GetLastAcquisitions { | ||||
| 1447 | my ($data,$max) = @_; | ||||
| 1448 | |||||
| 1449 | my $itemtype = C4::Context->preference('item-level_itypes') ? 'itype' : 'itemtype'; | ||||
| 1450 | |||||
| 1451 | my $number_of_branches = @{$data->{branches}}; | ||||
| 1452 | my $number_of_itemtypes = @{$data->{itemtypes}}; | ||||
| 1453 | |||||
| 1454 | |||||
| 1455 | my @where = ('WHERE 1 '); | ||||
| 1456 | $number_of_branches and push @where | ||||
| 1457 | , 'AND holdingbranch IN (' | ||||
| 1458 | , join(',', ('?') x $number_of_branches ) | ||||
| 1459 | , ')' | ||||
| 1460 | ; | ||||
| 1461 | |||||
| 1462 | $number_of_itemtypes and push @where | ||||
| 1463 | , "AND $itemtype IN (" | ||||
| 1464 | , join(',', ('?') x $number_of_itemtypes ) | ||||
| 1465 | , ')' | ||||
| 1466 | ; | ||||
| 1467 | |||||
| 1468 | my $query = "SELECT biblio.biblionumber as biblionumber, title, dateaccessioned | ||||
| 1469 | FROM items RIGHT JOIN biblio ON (items.biblionumber=biblio.biblionumber) | ||||
| 1470 | RIGHT JOIN biblioitems ON (items.biblioitemnumber=biblioitems.biblioitemnumber) | ||||
| 1471 | @where | ||||
| 1472 | GROUP BY biblio.biblionumber | ||||
| 1473 | ORDER BY dateaccessioned DESC LIMIT $max"; | ||||
| 1474 | |||||
| 1475 | my $dbh = C4::Context->dbh; | ||||
| 1476 | my $sth = $dbh->prepare($query); | ||||
| 1477 | |||||
| 1478 | $sth->execute((@{$data->{branches}}, @{$data->{itemtypes}})); | ||||
| 1479 | |||||
| 1480 | my @results; | ||||
| 1481 | while( my $row = $sth->fetchrow_hashref){ | ||||
| 1482 | push @results, {date => $row->{dateaccessioned} | ||||
| 1483 | , biblionumber => $row->{biblionumber} | ||||
| 1484 | , title => $row->{title}}; | ||||
| 1485 | } | ||||
| 1486 | |||||
| 1487 | return @results; | ||||
| 1488 | } | ||||
| 1489 | |||||
| 1490 | =head2 GetItemnumbersForBiblio | ||||
| 1491 | |||||
| - - | |||||
| 1498 | sub GetItemnumbersForBiblio { | ||||
| 1499 | my $biblionumber = shift; | ||||
| 1500 | my @items; | ||||
| 1501 | my $dbh = C4::Context->dbh; | ||||
| 1502 | my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?"); | ||||
| 1503 | $sth->execute($biblionumber); | ||||
| 1504 | while (my $result = $sth->fetchrow_hashref) { | ||||
| 1505 | push @items, $result->{'itemnumber'}; | ||||
| 1506 | } | ||||
| 1507 | return \@items; | ||||
| 1508 | } | ||||
| 1509 | |||||
| 1510 | =head2 get_itemnumbers_of | ||||
| 1511 | |||||
| - - | |||||
| 1522 | sub get_itemnumbers_of { | ||||
| 1523 | my @biblionumbers = @_; | ||||
| 1524 | |||||
| 1525 | my $dbh = C4::Context->dbh; | ||||
| 1526 | |||||
| 1527 | my $query = ' | ||||
| 1528 | SELECT itemnumber, | ||||
| 1529 | biblionumber | ||||
| 1530 | FROM items | ||||
| 1531 | WHERE biblionumber IN (?' . ( ',?' x scalar @biblionumbers - 1 ) . ') | ||||
| 1532 | '; | ||||
| 1533 | my $sth = $dbh->prepare($query); | ||||
| 1534 | $sth->execute(@biblionumbers); | ||||
| 1535 | |||||
| 1536 | my %itemnumbers_of; | ||||
| 1537 | |||||
| 1538 | while ( my ( $itemnumber, $biblionumber ) = $sth->fetchrow_array ) { | ||||
| 1539 | push @{ $itemnumbers_of{$biblionumber} }, $itemnumber; | ||||
| 1540 | } | ||||
| 1541 | |||||
| 1542 | return \%itemnumbers_of; | ||||
| 1543 | } | ||||
| 1544 | |||||
| 1545 | =head2 get_hostitemnumbers_of | ||||
| 1546 | |||||
| - - | |||||
| 1557 | sub get_hostitemnumbers_of { | ||||
| 1558 | my ($biblionumber) = @_; | ||||
| 1559 | my $marcrecord = GetMarcBiblio($biblionumber); | ||||
| 1560 | my (@returnhostitemnumbers,$tag, $biblio_s, $item_s); | ||||
| 1561 | |||||
| 1562 | my $marcflavor = C4::Context->preference('marcflavour'); | ||||
| 1563 | if ($marcflavor eq 'MARC21' || $marcflavor eq 'NORMARC') { | ||||
| 1564 | $tag='773'; | ||||
| 1565 | $biblio_s='0'; | ||||
| 1566 | $item_s='9'; | ||||
| 1567 | } elsif ($marcflavor eq 'UNIMARC') { | ||||
| 1568 | $tag='461'; | ||||
| 1569 | $biblio_s='0'; | ||||
| 1570 | $item_s='9'; | ||||
| 1571 | } | ||||
| 1572 | |||||
| 1573 | foreach my $hostfield ( $marcrecord->field($tag) ) { | ||||
| 1574 | my $hostbiblionumber = $hostfield->subfield($biblio_s); | ||||
| 1575 | my $linkeditemnumber = $hostfield->subfield($item_s); | ||||
| 1576 | my @itemnumbers; | ||||
| 1577 | if (my $itemnumbers = get_itemnumbers_of($hostbiblionumber)->{$hostbiblionumber}) | ||||
| 1578 | { | ||||
| 1579 | @itemnumbers = @$itemnumbers; | ||||
| 1580 | } | ||||
| 1581 | foreach my $itemnumber (@itemnumbers){ | ||||
| 1582 | if ($itemnumber eq $linkeditemnumber){ | ||||
| 1583 | push (@returnhostitemnumbers,$itemnumber); | ||||
| 1584 | last; | ||||
| 1585 | } | ||||
| 1586 | } | ||||
| 1587 | } | ||||
| 1588 | return @returnhostitemnumbers; | ||||
| 1589 | } | ||||
| 1590 | |||||
| 1591 | |||||
| 1592 | =head2 GetItemnumberFromBarcode | ||||
| 1593 | |||||
| - - | |||||
| 1598 | sub GetItemnumberFromBarcode { | ||||
| 1599 | my ($barcode) = @_; | ||||
| 1600 | my $dbh = C4::Context->dbh; | ||||
| 1601 | |||||
| 1602 | my $rq = | ||||
| 1603 | $dbh->prepare("SELECT itemnumber FROM items WHERE items.barcode=?"); | ||||
| 1604 | $rq->execute($barcode); | ||||
| 1605 | my ($result) = $rq->fetchrow; | ||||
| 1606 | return ($result); | ||||
| 1607 | } | ||||
| 1608 | |||||
| 1609 | =head2 GetBarcodeFromItemnumber | ||||
| 1610 | |||||
| - - | |||||
| 1615 | sub GetBarcodeFromItemnumber { | ||||
| 1616 | my ($itemnumber) = @_; | ||||
| 1617 | my $dbh = C4::Context->dbh; | ||||
| 1618 | |||||
| 1619 | my $rq = | ||||
| 1620 | $dbh->prepare("SELECT barcode FROM items WHERE items.itemnumber=?"); | ||||
| 1621 | $rq->execute($itemnumber); | ||||
| 1622 | my ($result) = $rq->fetchrow; | ||||
| 1623 | return ($result); | ||||
| 1624 | } | ||||
| 1625 | |||||
| 1626 | =head2 GetHiddenItemnumbers | ||||
| 1627 | |||||
| - - | |||||
| 1636 | # spent 122ms (1.90+120) within C4::Items::GetHiddenItemnumbers which was called 32 times, avg 3.81ms/call:
# 32 times (1.90ms+120ms) by C4::Search::searchResults at line 1851 of /usr/share/koha/lib/C4/Search.pm, avg 3.81ms/call | ||||
| 1637 | 320 | 1.20ms | my (@items) = @_; | ||
| 1638 | my @resultitems; | ||||
| 1639 | |||||
| 1640 | 32 | 2.48ms | my $yaml = C4::Context->preference('OpacHiddenItems'); # spent 2.48ms making 32 calls to C4::Context::preference, avg 77µs/call | ||
| 1641 | $yaml = "$yaml\n\n"; # YAML is anal on ending \n. Surplus does not hurt | ||||
| 1642 | my $hidingrules; | ||||
| 1643 | 32 | 320µs | eval { | ||
| 1644 | 32 | 82.3ms | $hidingrules = YAML::Load($yaml); # spent 82.3ms making 32 calls to YAML::Load, avg 2.57ms/call | ||
| 1645 | }; | ||||
| 1646 | if ($@) { | ||||
| 1647 | warn "Unable to parse OpacHiddenItems syspref : $@"; | ||||
| 1648 | return (); | ||||
| 1649 | } | ||||
| 1650 | 32 | 35.2ms | my $dbh = C4::Context->dbh; # spent 35.2ms making 32 calls to C4::Context::dbh, avg 1.10ms/call | ||
| 1651 | |||||
| 1652 | # For each item | ||||
| 1653 | foreach my $item (@items) { | ||||
| 1654 | |||||
| 1655 | # We check each rule | ||||
| 1656 | 32 | 275µs | foreach my $field (keys %$hidingrules) { | ||
| 1657 | my $val; | ||||
| 1658 | if (exists $item->{$field}) { | ||||
| 1659 | $val = $item->{$field}; | ||||
| 1660 | } | ||||
| 1661 | else { | ||||
| 1662 | my $query = "SELECT $field from items where itemnumber = ?"; | ||||
| 1663 | $val = $dbh->selectrow_array($query, undef, $item->{'itemnumber'}); | ||||
| 1664 | } | ||||
| 1665 | $val = '' unless defined $val; | ||||
| 1666 | |||||
| 1667 | # If the results matches the values in the yaml file | ||||
| 1668 | if (any { $val eq $_ } @{$hidingrules->{$field}}) { | ||||
| 1669 | |||||
| 1670 | # We add the itemnumber to the list | ||||
| 1671 | push @resultitems, $item->{'itemnumber'}; | ||||
| 1672 | |||||
| 1673 | # If at least one rule matched for an item, no need to test the others | ||||
| 1674 | last; | ||||
| 1675 | } | ||||
| 1676 | } | ||||
| 1677 | } | ||||
| 1678 | return @resultitems; | ||||
| 1679 | } | ||||
| 1680 | |||||
| 1681 | =head3 get_item_authorised_values | ||||
| 1682 | |||||
| - - | |||||
| 1707 | sub get_item_authorised_values { | ||||
| 1708 | my $itemnumber = shift; | ||||
| 1709 | |||||
| 1710 | # assume that these entries in the authorised_value table are item level. | ||||
| 1711 | my $query = q(SELECT distinct authorised_value, kohafield | ||||
| 1712 | FROM marc_subfield_structure | ||||
| 1713 | WHERE kohafield like 'item%' | ||||
| 1714 | AND authorised_value != '' ); | ||||
| 1715 | |||||
| 1716 | my $itemlevel_authorised_values = C4::Context->dbh->selectall_hashref( $query, 'authorised_value' ); | ||||
| 1717 | my $iteminfo = GetItem( $itemnumber ); | ||||
| 1718 | # warn( Data::Dumper->Dump( [ $itemlevel_authorised_values ], [ 'itemlevel_authorised_values' ] ) ); | ||||
| 1719 | my $return; | ||||
| 1720 | foreach my $this_authorised_value ( keys %$itemlevel_authorised_values ) { | ||||
| 1721 | my $field = $itemlevel_authorised_values->{ $this_authorised_value }->{'kohafield'}; | ||||
| 1722 | $field =~ s/^items\.//; | ||||
| 1723 | if ( exists $iteminfo->{ $field } ) { | ||||
| 1724 | $return->{ $this_authorised_value } = $iteminfo->{ $field }; | ||||
| 1725 | } | ||||
| 1726 | } | ||||
| 1727 | # warn( Data::Dumper->Dump( [ $return ], [ 'return' ] ) ); | ||||
| 1728 | return $return; | ||||
| 1729 | } | ||||
| 1730 | |||||
| 1731 | =head3 get_authorised_value_images | ||||
| 1732 | |||||
| - - | |||||
| 1754 | sub get_authorised_value_images { | ||||
| 1755 | my $authorised_values = shift; | ||||
| 1756 | |||||
| 1757 | my @imagelist; | ||||
| 1758 | |||||
| 1759 | my $authorised_value_list = GetAuthorisedValues(); | ||||
| 1760 | # warn ( Data::Dumper->Dump( [ $authorised_value_list ], [ 'authorised_value_list' ] ) ); | ||||
| 1761 | foreach my $this_authorised_value ( @$authorised_value_list ) { | ||||
| 1762 | if ( exists $authorised_values->{ $this_authorised_value->{'category'} } | ||||
| 1763 | && $authorised_values->{ $this_authorised_value->{'category'} } eq $this_authorised_value->{'authorised_value'} ) { | ||||
| 1764 | # warn ( Data::Dumper->Dump( [ $this_authorised_value ], [ 'this_authorised_value' ] ) ); | ||||
| 1765 | if ( defined $this_authorised_value->{'imageurl'} ) { | ||||
| 1766 | push @imagelist, { imageurl => C4::Koha::getitemtypeimagelocation( 'intranet', $this_authorised_value->{'imageurl'} ), | ||||
| 1767 | label => $this_authorised_value->{'lib'}, | ||||
| 1768 | category => $this_authorised_value->{'category'}, | ||||
| 1769 | value => $this_authorised_value->{'authorised_value'}, }; | ||||
| 1770 | } | ||||
| 1771 | } | ||||
| 1772 | } | ||||
| 1773 | |||||
| 1774 | # warn ( Data::Dumper->Dump( [ \@imagelist ], [ 'imagelist' ] ) ); | ||||
| 1775 | return \@imagelist; | ||||
| 1776 | |||||
| 1777 | } | ||||
| 1778 | |||||
| 1779 | =head1 LIMITED USE FUNCTIONS | ||||
| 1780 | |||||
| - - | |||||
| 1789 | =head2 GetMarcItem | ||||
| 1790 | |||||
| - - | |||||
| 1800 | sub GetMarcItem { | ||||
| 1801 | my ( $biblionumber, $itemnumber ) = @_; | ||||
| 1802 | |||||
| 1803 | # GetMarcItem has been revised so that it does the following: | ||||
| 1804 | # 1. Gets the item information from the items table. | ||||
| 1805 | # 2. Converts it to a MARC field for storage in the bib record. | ||||
| 1806 | # | ||||
| 1807 | # The previous behavior was: | ||||
| 1808 | # 1. Get the bib record. | ||||
| 1809 | # 2. Return the MARC tag corresponding to the item record. | ||||
| 1810 | # | ||||
| 1811 | # The difference is that one treats the items row as authoritative, | ||||
| 1812 | # while the other treats the MARC representation as authoritative | ||||
| 1813 | # under certain circumstances. | ||||
| 1814 | |||||
| 1815 | my $itemrecord = GetItem($itemnumber); | ||||
| 1816 | |||||
| 1817 | # Tack on 'items.' prefix to column names so that TransformKohaToMarc will work. | ||||
| 1818 | # Also, don't emit a subfield if the underlying field is blank. | ||||
| 1819 | |||||
| 1820 | |||||
| 1821 | return Item2Marc($itemrecord,$biblionumber); | ||||
| 1822 | |||||
| 1823 | } | ||||
| 1824 | sub Item2Marc { | ||||
| 1825 | my ($itemrecord,$biblionumber)=@_; | ||||
| 1826 | my $mungeditem = { | ||||
| 1827 | map { | ||||
| 1828 | defined($itemrecord->{$_}) && $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : () | ||||
| 1829 | } keys %{ $itemrecord } | ||||
| 1830 | }; | ||||
| 1831 | my $itemmarc = TransformKohaToMarc($mungeditem); | ||||
| 1832 | my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField("items.itemnumber",GetFrameworkCode($biblionumber)||''); | ||||
| 1833 | |||||
| 1834 | my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'}); | ||||
| 1835 | if (defined $unlinked_item_subfields and $#$unlinked_item_subfields > -1) { | ||||
| 1836 | foreach my $field ($itemmarc->field($itemtag)){ | ||||
| 1837 | $field->add_subfields(@$unlinked_item_subfields); | ||||
| 1838 | } | ||||
| 1839 | } | ||||
| 1840 | return $itemmarc; | ||||
| 1841 | } | ||||
| 1842 | |||||
| 1843 | =head1 PRIVATE FUNCTIONS AND VARIABLES | ||||
| 1844 | |||||
| - - | |||||
| 1851 | =head2 %derived_columns | ||||
| 1852 | |||||
| - - | |||||
| 1868 | 1 | 6µs | my %derived_columns = ( | ||
| 1869 | 'items.cn_sort' => { | ||||
| 1870 | 'itemcallnumber' => 1, | ||||
| 1871 | 'items.cn_source' => 1, | ||||
| 1872 | 'BUILDER' => \&_calc_items_cn_sort, | ||||
| 1873 | } | ||||
| 1874 | ); | ||||
| 1875 | |||||
| 1876 | =head2 _set_derived_columns_for_add | ||||
| 1877 | |||||
| - - | |||||
| 1886 | sub _set_derived_columns_for_add { | ||||
| 1887 | my $item = shift; | ||||
| 1888 | |||||
| 1889 | foreach my $column (keys %derived_columns) { | ||||
| 1890 | my $builder = $derived_columns{$column}->{'BUILDER'}; | ||||
| 1891 | my $source_values = {}; | ||||
| 1892 | foreach my $source_column (keys %{ $derived_columns{$column} }) { | ||||
| 1893 | next if $source_column eq 'BUILDER'; | ||||
| 1894 | $source_values->{$source_column} = $item->{$source_column}; | ||||
| 1895 | } | ||||
| 1896 | $builder->($item, $source_values); | ||||
| 1897 | } | ||||
| 1898 | } | ||||
| 1899 | |||||
| 1900 | =head2 _set_derived_columns_for_mod | ||||
| 1901 | |||||
| - - | |||||
| 1921 | sub _set_derived_columns_for_mod { | ||||
| 1922 | my $item = shift; | ||||
| 1923 | |||||
| 1924 | foreach my $column (keys %derived_columns) { | ||||
| 1925 | my $builder = $derived_columns{$column}->{'BUILDER'}; | ||||
| 1926 | my $source_values = {}; | ||||
| 1927 | my %missing_sources = (); | ||||
| 1928 | my $must_recalc = 0; | ||||
| 1929 | foreach my $source_column (keys %{ $derived_columns{$column} }) { | ||||
| 1930 | next if $source_column eq 'BUILDER'; | ||||
| 1931 | if (exists $item->{$source_column}) { | ||||
| 1932 | $must_recalc = 1; | ||||
| 1933 | $source_values->{$source_column} = $item->{$source_column}; | ||||
| 1934 | } else { | ||||
| 1935 | $missing_sources{$source_column} = 1; | ||||
| 1936 | } | ||||
| 1937 | } | ||||
| 1938 | if ($must_recalc) { | ||||
| 1939 | foreach my $source_column (keys %missing_sources) { | ||||
| 1940 | $source_values->{$source_column} = _get_single_item_column($source_column, $item->{'itemnumber'}); | ||||
| 1941 | } | ||||
| 1942 | $builder->($item, $source_values); | ||||
| 1943 | } | ||||
| 1944 | } | ||||
| 1945 | } | ||||
| 1946 | |||||
| 1947 | =head2 _do_column_fixes_for_mod | ||||
| 1948 | |||||
| - - | |||||
| 1960 | sub _do_column_fixes_for_mod { | ||||
| 1961 | my $item = shift; | ||||
| 1962 | |||||
| 1963 | if (exists $item->{'notforloan'} and | ||||
| 1964 | (not defined $item->{'notforloan'} or $item->{'notforloan'} eq '')) { | ||||
| 1965 | $item->{'notforloan'} = 0; | ||||
| 1966 | } | ||||
| 1967 | if (exists $item->{'damaged'} and | ||||
| 1968 | (not defined $item->{'damaged'} or $item->{'damaged'} eq '')) { | ||||
| 1969 | $item->{'damaged'} = 0; | ||||
| 1970 | } | ||||
| 1971 | if (exists $item->{'itemlost'} and | ||||
| 1972 | (not defined $item->{'itemlost'} or $item->{'itemlost'} eq '')) { | ||||
| 1973 | $item->{'itemlost'} = 0; | ||||
| 1974 | } | ||||
| 1975 | if (exists $item->{'wthdrawn'} and | ||||
| 1976 | (not defined $item->{'wthdrawn'} or $item->{'wthdrawn'} eq '')) { | ||||
| 1977 | $item->{'wthdrawn'} = 0; | ||||
| 1978 | } | ||||
| 1979 | if (exists $item->{'location'} && !exists $item->{'permanent_location'}) { | ||||
| 1980 | $item->{'permanent_location'} = $item->{'location'}; | ||||
| 1981 | } | ||||
| 1982 | if (exists $item->{'timestamp'}) { | ||||
| 1983 | delete $item->{'timestamp'}; | ||||
| 1984 | } | ||||
| 1985 | } | ||||
| 1986 | |||||
| 1987 | =head2 _get_single_item_column | ||||
| 1988 | |||||
| - - | |||||
| 1996 | sub _get_single_item_column { | ||||
| 1997 | my $column = shift; | ||||
| 1998 | my $itemnumber = shift; | ||||
| 1999 | |||||
| 2000 | my $dbh = C4::Context->dbh; | ||||
| 2001 | my $sth = $dbh->prepare("SELECT $column FROM items WHERE itemnumber = ?"); | ||||
| 2002 | $sth->execute($itemnumber); | ||||
| 2003 | my ($value) = $sth->fetchrow(); | ||||
| 2004 | return $value; | ||||
| 2005 | } | ||||
| 2006 | |||||
| 2007 | =head2 _calc_items_cn_sort | ||||
| 2008 | |||||
| - - | |||||
| 2015 | sub _calc_items_cn_sort { | ||||
| 2016 | my $item = shift; | ||||
| 2017 | my $source_values = shift; | ||||
| 2018 | |||||
| 2019 | $item->{'items.cn_sort'} = GetClassSort($source_values->{'items.cn_source'}, $source_values->{'itemcallnumber'}, ""); | ||||
| 2020 | } | ||||
| 2021 | |||||
| 2022 | =head2 _set_defaults_for_add | ||||
| 2023 | |||||
| - - | |||||
| 2057 | sub _set_defaults_for_add { | ||||
| 2058 | my $item = shift; | ||||
| 2059 | $item->{dateaccessioned} ||= C4::Dates->new->output('iso'); | ||||
| 2060 | $item->{$_} ||= 0 for (qw( notforloan damaged itemlost wthdrawn)); | ||||
| 2061 | } | ||||
| 2062 | |||||
| 2063 | =head2 _koha_new_item | ||||
| 2064 | |||||
| - - | |||||
| 2071 | sub _koha_new_item { | ||||
| 2072 | my ( $item, $barcode ) = @_; | ||||
| 2073 | my $dbh=C4::Context->dbh; | ||||
| 2074 | my $error; | ||||
| 2075 | my $query = | ||||
| 2076 | "INSERT INTO items SET | ||||
| 2077 | biblionumber = ?, | ||||
| 2078 | biblioitemnumber = ?, | ||||
| 2079 | barcode = ?, | ||||
| 2080 | dateaccessioned = ?, | ||||
| 2081 | booksellerid = ?, | ||||
| 2082 | homebranch = ?, | ||||
| 2083 | price = ?, | ||||
| 2084 | replacementprice = ?, | ||||
| 2085 | replacementpricedate = ?, | ||||
| 2086 | datelastborrowed = ?, | ||||
| 2087 | datelastseen = ?, | ||||
| 2088 | stack = ?, | ||||
| 2089 | notforloan = ?, | ||||
| 2090 | damaged = ?, | ||||
| 2091 | itemlost = ?, | ||||
| 2092 | wthdrawn = ?, | ||||
| 2093 | itemcallnumber = ?, | ||||
| 2094 | coded_location_qualifier = ?, | ||||
| 2095 | restricted = ?, | ||||
| 2096 | itemnotes = ?, | ||||
| 2097 | holdingbranch = ?, | ||||
| 2098 | paidfor = ?, | ||||
| 2099 | location = ?, | ||||
| 2100 | permanent_location = ?, | ||||
| 2101 | onloan = ?, | ||||
| 2102 | issues = ?, | ||||
| 2103 | renewals = ?, | ||||
| 2104 | reserves = ?, | ||||
| 2105 | cn_source = ?, | ||||
| 2106 | cn_sort = ?, | ||||
| 2107 | ccode = ?, | ||||
| 2108 | itype = ?, | ||||
| 2109 | materials = ?, | ||||
| 2110 | uri = ?, | ||||
| 2111 | enumchron = ?, | ||||
| 2112 | more_subfields_xml = ?, | ||||
| 2113 | copynumber = ?, | ||||
| 2114 | stocknumber = ? | ||||
| 2115 | "; | ||||
| 2116 | my $sth = $dbh->prepare($query); | ||||
| 2117 | my $today = C4::Dates->today('iso'); | ||||
| 2118 | $sth->execute( | ||||
| 2119 | $item->{'biblionumber'}, | ||||
| 2120 | $item->{'biblioitemnumber'}, | ||||
| 2121 | $barcode, | ||||
| 2122 | $item->{'dateaccessioned'}, | ||||
| 2123 | $item->{'booksellerid'}, | ||||
| 2124 | $item->{'homebranch'}, | ||||
| 2125 | $item->{'price'}, | ||||
| 2126 | $item->{'replacementprice'}, | ||||
| 2127 | $item->{'replacementpricedate'} || $today, | ||||
| 2128 | $item->{datelastborrowed}, | ||||
| 2129 | $item->{datelastseen} || $today, | ||||
| 2130 | $item->{stack}, | ||||
| 2131 | $item->{'notforloan'}, | ||||
| 2132 | $item->{'damaged'}, | ||||
| 2133 | $item->{'itemlost'}, | ||||
| 2134 | $item->{'wthdrawn'}, | ||||
| 2135 | $item->{'itemcallnumber'}, | ||||
| 2136 | $item->{'coded_location_qualifier'}, | ||||
| 2137 | $item->{'restricted'}, | ||||
| 2138 | $item->{'itemnotes'}, | ||||
| 2139 | $item->{'holdingbranch'}, | ||||
| 2140 | $item->{'paidfor'}, | ||||
| 2141 | $item->{'location'}, | ||||
| 2142 | $item->{'permanent_location'}, | ||||
| 2143 | $item->{'onloan'}, | ||||
| 2144 | $item->{'issues'}, | ||||
| 2145 | $item->{'renewals'}, | ||||
| 2146 | $item->{'reserves'}, | ||||
| 2147 | $item->{'items.cn_source'}, | ||||
| 2148 | $item->{'items.cn_sort'}, | ||||
| 2149 | $item->{'ccode'}, | ||||
| 2150 | $item->{'itype'}, | ||||
| 2151 | $item->{'materials'}, | ||||
| 2152 | $item->{'uri'}, | ||||
| 2153 | $item->{'enumchron'}, | ||||
| 2154 | $item->{'more_subfields_xml'}, | ||||
| 2155 | $item->{'copynumber'}, | ||||
| 2156 | $item->{'stocknumber'}, | ||||
| 2157 | ); | ||||
| 2158 | |||||
| 2159 | my $itemnumber; | ||||
| 2160 | if ( defined $sth->errstr ) { | ||||
| 2161 | $error.="ERROR in _koha_new_item $query".$sth->errstr; | ||||
| 2162 | } | ||||
| 2163 | else { | ||||
| 2164 | $itemnumber = $dbh->{'mysql_insertid'}; | ||||
| 2165 | } | ||||
| 2166 | |||||
| 2167 | return ( $itemnumber, $error ); | ||||
| 2168 | } | ||||
| 2169 | |||||
| 2170 | =head2 MoveItemFromBiblio | ||||
| 2171 | |||||
| - - | |||||
| 2180 | sub MoveItemFromBiblio { | ||||
| 2181 | my ($itemnumber, $frombiblio, $tobiblio) = @_; | ||||
| 2182 | my $dbh = C4::Context->dbh; | ||||
| 2183 | my $sth = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber = ?"); | ||||
| 2184 | $sth->execute( $tobiblio ); | ||||
| 2185 | my ( $tobiblioitem ) = $sth->fetchrow(); | ||||
| 2186 | $sth = $dbh->prepare("UPDATE items SET biblioitemnumber = ?, biblionumber = ? WHERE itemnumber = ? AND biblionumber = ?"); | ||||
| 2187 | my $return = $sth->execute($tobiblioitem, $tobiblio, $itemnumber, $frombiblio); | ||||
| 2188 | if ($return == 1) { | ||||
| 2189 | ModZebra( $tobiblio, "specialUpdate", "biblioserver" ); | ||||
| 2190 | ModZebra( $frombiblio, "specialUpdate", "biblioserver" ); | ||||
| 2191 | # Checking if the item we want to move is in an order | ||||
| 2192 | require C4::Acquisition; | ||||
| 2193 | my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber); | ||||
| 2194 | if ($order) { | ||||
| 2195 | # Replacing the biblionumber within the order if necessary | ||||
| 2196 | $order->{'biblionumber'} = $tobiblio; | ||||
| 2197 | C4::Acquisition::ModOrder($order); | ||||
| 2198 | } | ||||
| 2199 | return $tobiblio; | ||||
| 2200 | } | ||||
| 2201 | return; | ||||
| 2202 | } | ||||
| 2203 | |||||
| 2204 | =head2 DelItemCheck | ||||
| 2205 | |||||
| - - | |||||
| 2212 | sub DelItemCheck { | ||||
| 2213 | my ( $dbh, $biblionumber, $itemnumber ) = @_; | ||||
| 2214 | my $error; | ||||
| 2215 | |||||
| 2216 | my $countanalytics=GetAnalyticsCount($itemnumber); | ||||
| 2217 | |||||
| 2218 | |||||
| 2219 | # check that there is no issue on this item before deletion. | ||||
| 2220 | my $sth=$dbh->prepare("select * from issues i where i.itemnumber=?"); | ||||
| 2221 | $sth->execute($itemnumber); | ||||
| 2222 | |||||
| 2223 | my $item = GetItem($itemnumber); | ||||
| 2224 | my $onloan=$sth->fetchrow; | ||||
| 2225 | |||||
| 2226 | if ($onloan){ | ||||
| 2227 | $error = "book_on_loan" | ||||
| 2228 | } | ||||
| 2229 | elsif ( !( C4::Context->userenv->{flags} & 1 ) | ||||
| 2230 | and C4::Context->preference("IndependantBranches") | ||||
| 2231 | and ( C4::Context->userenv->{branch} ne $item->{'homebranch'} ) ) | ||||
| 2232 | { | ||||
| 2233 | $error = "not_same_branch"; | ||||
| 2234 | } | ||||
| 2235 | else{ | ||||
| 2236 | # check it doesnt have a waiting reserve | ||||
| 2237 | $sth=$dbh->prepare("SELECT * FROM reserves WHERE (found = 'W' or found = 'T') AND itemnumber = ?"); | ||||
| 2238 | $sth->execute($itemnumber); | ||||
| 2239 | my $reserve=$sth->fetchrow; | ||||
| 2240 | if ($reserve){ | ||||
| 2241 | $error = "book_reserved"; | ||||
| 2242 | } elsif ($countanalytics > 0){ | ||||
| 2243 | $error = "linked_analytics"; | ||||
| 2244 | } else { | ||||
| 2245 | DelItem($dbh, $biblionumber, $itemnumber); | ||||
| 2246 | return 1; | ||||
| 2247 | } | ||||
| 2248 | } | ||||
| 2249 | return $error; | ||||
| 2250 | } | ||||
| 2251 | |||||
| 2252 | =head2 _koha_modify_item | ||||
| 2253 | |||||
| - - | |||||
| 2261 | sub _koha_modify_item { | ||||
| 2262 | my ( $item ) = @_; | ||||
| 2263 | my $dbh=C4::Context->dbh; | ||||
| 2264 | my $error; | ||||
| 2265 | |||||
| 2266 | my $query = "UPDATE items SET "; | ||||
| 2267 | my @bind; | ||||
| 2268 | for my $key ( keys %$item ) { | ||||
| 2269 | next if ( $key eq 'itemnumber' ); | ||||
| 2270 | $query.="$key=?,"; | ||||
| 2271 | push @bind, $item->{$key}; | ||||
| 2272 | } | ||||
| 2273 | $query =~ s/,$//; | ||||
| 2274 | $query .= " WHERE itemnumber=?"; | ||||
| 2275 | push @bind, $item->{'itemnumber'}; | ||||
| 2276 | my $sth = C4::Context->dbh->prepare($query); | ||||
| 2277 | $sth->execute(@bind); | ||||
| 2278 | if ( C4::Context->dbh->errstr ) { | ||||
| 2279 | $error.="ERROR in _koha_modify_item $query".$dbh->errstr; | ||||
| 2280 | warn $error; | ||||
| 2281 | } | ||||
| 2282 | return ($item->{'itemnumber'},$error); | ||||
| 2283 | } | ||||
| 2284 | |||||
| 2285 | =head2 _koha_delete_item | ||||
| 2286 | |||||
| - - | |||||
| 2293 | sub _koha_delete_item { | ||||
| 2294 | my ( $dbh, $itemnum ) = @_; | ||||
| 2295 | |||||
| 2296 | # save the deleted item to deleteditems table | ||||
| 2297 | my $sth = $dbh->prepare("SELECT * FROM items WHERE itemnumber=?"); | ||||
| 2298 | $sth->execute($itemnum); | ||||
| 2299 | my $data = $sth->fetchrow_hashref(); | ||||
| 2300 | my $query = "INSERT INTO deleteditems SET "; | ||||
| 2301 | my @bind = (); | ||||
| 2302 | foreach my $key ( keys %$data ) { | ||||
| 2303 | $query .= "$key = ?,"; | ||||
| 2304 | push( @bind, $data->{$key} ); | ||||
| 2305 | } | ||||
| 2306 | $query =~ s/\,$//; | ||||
| 2307 | $sth = $dbh->prepare($query); | ||||
| 2308 | $sth->execute(@bind); | ||||
| 2309 | |||||
| 2310 | # delete from items table | ||||
| 2311 | $sth = $dbh->prepare("DELETE FROM items WHERE itemnumber=?"); | ||||
| 2312 | $sth->execute($itemnum); | ||||
| 2313 | return; | ||||
| 2314 | } | ||||
| 2315 | |||||
| 2316 | =head2 _marc_from_item_hash | ||||
| 2317 | |||||
| - - | |||||
| 2331 | sub _marc_from_item_hash { | ||||
| 2332 | my $item = shift; | ||||
| 2333 | my $frameworkcode = shift; | ||||
| 2334 | my $unlinked_item_subfields; | ||||
| 2335 | if (@_) { | ||||
| 2336 | $unlinked_item_subfields = shift; | ||||
| 2337 | } | ||||
| 2338 | |||||
| 2339 | # Tack on 'items.' prefix to column names so lookup from MARC frameworks will work | ||||
| 2340 | # Also, don't emit a subfield if the underlying field is blank. | ||||
| 2341 | my $mungeditem = { map { (defined($item->{$_}) and $item->{$_} ne '') ? | ||||
| 2342 | (/^items\./ ? ($_ => $item->{$_}) : ("items.$_" => $item->{$_})) | ||||
| 2343 | : () } keys %{ $item } }; | ||||
| 2344 | |||||
| 2345 | my $item_marc = MARC::Record->new(); | ||||
| 2346 | foreach my $item_field ( keys %{$mungeditem} ) { | ||||
| 2347 | my ( $tag, $subfield ) = GetMarcFromKohaField( $item_field, $frameworkcode ); | ||||
| 2348 | next unless defined $tag and defined $subfield; # skip if not mapped to MARC field | ||||
| 2349 | my @values = split(/\s?\|\s?/, $mungeditem->{$item_field}, -1); | ||||
| 2350 | foreach my $value (@values){ | ||||
| 2351 | if ( my $field = $item_marc->field($tag) ) { | ||||
| 2352 | $field->add_subfields( $subfield => $value ); | ||||
| 2353 | } else { | ||||
| 2354 | my $add_subfields = []; | ||||
| 2355 | if (defined $unlinked_item_subfields and ref($unlinked_item_subfields) eq 'ARRAY' and $#$unlinked_item_subfields > -1) { | ||||
| 2356 | $add_subfields = $unlinked_item_subfields; | ||||
| 2357 | } | ||||
| 2358 | $item_marc->add_fields( $tag, " ", " ", $subfield => $value, @$add_subfields ); | ||||
| 2359 | } | ||||
| 2360 | } | ||||
| 2361 | } | ||||
| 2362 | |||||
| 2363 | return $item_marc; | ||||
| 2364 | } | ||||
| 2365 | |||||
| 2366 | =head2 _repack_item_errors | ||||
| 2367 | |||||
| - - | |||||
| 2373 | sub _repack_item_errors { | ||||
| 2374 | my $item_sequence_num = shift; | ||||
| 2375 | my $item_ref = shift; | ||||
| 2376 | my $error_ref = shift; | ||||
| 2377 | |||||
| 2378 | my @repacked_errors = (); | ||||
| 2379 | |||||
| 2380 | foreach my $error_code (sort keys %{ $error_ref }) { | ||||
| 2381 | my $repacked_error = {}; | ||||
| 2382 | $repacked_error->{'item_sequence'} = $item_sequence_num; | ||||
| 2383 | $repacked_error->{'item_barcode'} = exists($item_ref->{'barcode'}) ? $item_ref->{'barcode'} : ''; | ||||
| 2384 | $repacked_error->{'error_code'} = $error_code; | ||||
| 2385 | $repacked_error->{'error_information'} = $error_ref->{$error_code}; | ||||
| 2386 | push @repacked_errors, $repacked_error; | ||||
| 2387 | } | ||||
| 2388 | |||||
| 2389 | return @repacked_errors; | ||||
| 2390 | } | ||||
| 2391 | |||||
| 2392 | =head2 _get_unlinked_item_subfields | ||||
| 2393 | |||||
| - - | |||||
| 2398 | sub _get_unlinked_item_subfields { | ||||
| 2399 | my $original_item_marc = shift; | ||||
| 2400 | my $frameworkcode = shift; | ||||
| 2401 | |||||
| 2402 | my $marcstructure = GetMarcStructure(1, $frameworkcode); | ||||
| 2403 | |||||
| 2404 | # assume that this record has only one field, and that that | ||||
| 2405 | # field contains only the item information | ||||
| 2406 | my $subfields = []; | ||||
| 2407 | my @fields = $original_item_marc->fields(); | ||||
| 2408 | if ($#fields > -1) { | ||||
| 2409 | my $field = $fields[0]; | ||||
| 2410 | my $tag = $field->tag(); | ||||
| 2411 | foreach my $subfield ($field->subfields()) { | ||||
| 2412 | if (defined $subfield->[1] and | ||||
| 2413 | $subfield->[1] ne '' and | ||||
| 2414 | !$marcstructure->{$tag}->{$subfield->[0]}->{'kohafield'}) { | ||||
| 2415 | push @$subfields, $subfield->[0] => $subfield->[1]; | ||||
| 2416 | } | ||||
| 2417 | } | ||||
| 2418 | } | ||||
| 2419 | return $subfields; | ||||
| 2420 | } | ||||
| 2421 | |||||
| 2422 | =head2 _get_unlinked_subfields_xml | ||||
| 2423 | |||||
| - - | |||||
| 2428 | sub _get_unlinked_subfields_xml { | ||||
| 2429 | my $unlinked_item_subfields = shift; | ||||
| 2430 | |||||
| 2431 | my $xml; | ||||
| 2432 | if (defined $unlinked_item_subfields and ref($unlinked_item_subfields) eq 'ARRAY' and $#$unlinked_item_subfields > -1) { | ||||
| 2433 | my $marc = MARC::Record->new(); | ||||
| 2434 | # use of tag 999 is arbitrary, and doesn't need to match the item tag | ||||
| 2435 | # used in the framework | ||||
| 2436 | $marc->append_fields(MARC::Field->new('999', ' ', ' ', @$unlinked_item_subfields)); | ||||
| 2437 | $marc->encoding("UTF-8"); | ||||
| 2438 | $xml = $marc->as_xml("USMARC"); | ||||
| 2439 | } | ||||
| 2440 | |||||
| 2441 | return $xml; | ||||
| 2442 | } | ||||
| 2443 | |||||
| 2444 | =head2 _parse_unlinked_item_subfields_from_xml | ||||
| 2445 | |||||
| - - | |||||
| 2450 | sub _parse_unlinked_item_subfields_from_xml { | ||||
| 2451 | my $xml = shift; | ||||
| 2452 | require C4::Charset; | ||||
| 2453 | return unless defined $xml and $xml ne ""; | ||||
| 2454 | my $marc = MARC::Record->new_from_xml(C4::Charset::StripNonXmlChars($xml),'UTF-8'); | ||||
| 2455 | my $unlinked_subfields = []; | ||||
| 2456 | my @fields = $marc->fields(); | ||||
| 2457 | if ($#fields > -1) { | ||||
| 2458 | foreach my $subfield ($fields[0]->subfields()) { | ||||
| 2459 | push @$unlinked_subfields, $subfield->[0] => $subfield->[1]; | ||||
| 2460 | } | ||||
| 2461 | } | ||||
| 2462 | return $unlinked_subfields; | ||||
| 2463 | } | ||||
| 2464 | |||||
| 2465 | =head2 GetAnalyticsCount | ||||
| 2466 | |||||
| - - | |||||
| 2473 | sub GetAnalyticsCount { | ||||
| 2474 | my ($itemnumber) = @_; | ||||
| 2475 | require C4::Search; | ||||
| 2476 | |||||
| 2477 | ### ZOOM search here | ||||
| 2478 | my $query; | ||||
| 2479 | $query= "hi=".$itemnumber; | ||||
| 2480 | my ($err,$res,$result) = C4::Search::SimpleSearch($query,0,10); | ||||
| 2481 | return ($result); | ||||
| 2482 | } | ||||
| 2483 | |||||
| 2484 | =head2 GetItemHolds | ||||
| 2485 | |||||
| - - | |||||
| 2495 | sub GetItemHolds { | ||||
| 2496 | my ($biblionumber, $itemnumber) = @_; | ||||
| 2497 | my $holds; | ||||
| 2498 | my $dbh = C4::Context->dbh; | ||||
| 2499 | my $query = "SELECT count(*) | ||||
| 2500 | FROM reserves | ||||
| 2501 | WHERE biblionumber=? AND itemnumber=?"; | ||||
| 2502 | my $sth = $dbh->prepare($query); | ||||
| 2503 | $sth->execute($biblionumber, $itemnumber); | ||||
| 2504 | $holds = $sth->fetchrow; | ||||
| 2505 | return $holds; | ||||
| 2506 | } | ||||
| 2507 | |||||
| 2508 | # Return the list of the column names of items table | ||||
| 2509 | sub _get_items_columns { | ||||
| 2510 | my $dbh = C4::Context->dbh; | ||||
| 2511 | my $sth = $dbh->column_info(undef, undef, 'items', '%'); | ||||
| 2512 | $sth->execute; | ||||
| 2513 | my $results = $sth->fetchall_hashref('COLUMN_NAME'); | ||||
| 2514 | return keys %$results; | ||||
| 2515 | } | ||||
| 2516 | |||||
| 2517 | =head2 SearchItems | ||||
| 2518 | |||||
| - - | |||||
| 2528 | sub SearchItems { | ||||
| 2529 | my ($field, $value) = @_; | ||||
| 2530 | |||||
| 2531 | my $dbh = C4::Context->dbh; | ||||
| 2532 | my @columns = _get_items_columns; | ||||
| 2533 | my $results = []; | ||||
| 2534 | if(0 < grep /^$field$/, @columns) { | ||||
| 2535 | my $query = "SELECT $field FROM items WHERE $field = ?"; | ||||
| 2536 | my $sth = $dbh->prepare( $query ); | ||||
| 2537 | $sth->execute( $value ); | ||||
| 2538 | $results = $sth->fetchall_arrayref({}); | ||||
| 2539 | } | ||||
| 2540 | return $results; | ||||
| 2541 | } | ||||
| 2542 | |||||
| 2543 | |||||
| 2544 | =head1 OTHER FUNCTIONS | ||||
| 2545 | |||||
| - - | |||||
| 2561 | sub _find_value { | ||||
| 2562 | my ( $tagfield, $insubfield, $record, $encoding ) = @_; | ||||
| 2563 | my @result; | ||||
| 2564 | my $indicator; | ||||
| 2565 | if ( $tagfield < 10 ) { | ||||
| 2566 | if ( $record->field($tagfield) ) { | ||||
| 2567 | push @result, $record->field($tagfield)->data(); | ||||
| 2568 | } else { | ||||
| 2569 | push @result, ""; | ||||
| 2570 | } | ||||
| 2571 | } else { | ||||
| 2572 | foreach my $field ( $record->field($tagfield) ) { | ||||
| 2573 | my @subfields = $field->subfields(); | ||||
| 2574 | foreach my $subfield (@subfields) { | ||||
| 2575 | if ( @$subfield[0] eq $insubfield ) { | ||||
| 2576 | push @result, @$subfield[1]; | ||||
| 2577 | $indicator = $field->indicator(1) . $field->indicator(2); | ||||
| 2578 | } | ||||
| 2579 | } | ||||
| 2580 | } | ||||
| 2581 | } | ||||
| 2582 | return ( $indicator, @result ); | ||||
| 2583 | } | ||||
| 2584 | |||||
| 2585 | |||||
| 2586 | =head2 PrepareItemrecordDisplay | ||||
| 2587 | |||||
| - - | |||||
| 2596 | sub PrepareItemrecordDisplay { | ||||
| 2597 | |||||
| 2598 | my ( $bibnum, $itemnum, $defaultvalues, $frameworkcode ) = @_; | ||||
| 2599 | |||||
| 2600 | my $dbh = C4::Context->dbh; | ||||
| 2601 | $frameworkcode = &GetFrameworkCode($bibnum) if $bibnum; | ||||
| 2602 | my ( $itemtagfield, $itemtagsubfield ) = &GetMarcFromKohaField( "items.itemnumber", $frameworkcode ); | ||||
| 2603 | my $tagslib = &GetMarcStructure( 1, $frameworkcode ); | ||||
| 2604 | |||||
| 2605 | # return nothing if we don't have found an existing framework. | ||||
| 2606 | return q{} unless $tagslib; | ||||
| 2607 | my $itemrecord; | ||||
| 2608 | if ($itemnum) { | ||||
| 2609 | $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum ); | ||||
| 2610 | } | ||||
| 2611 | my @loop_data; | ||||
| 2612 | |||||
| 2613 | my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : ""; | ||||
| 2614 | my $query = qq{ | ||||
| 2615 | SELECT authorised_value,lib FROM authorised_values | ||||
| 2616 | }; | ||||
| 2617 | $query .= qq{ | ||||
| 2618 | LEFT JOIN authorised_values_branches ON ( id = av_id ) | ||||
| 2619 | } if $branch_limit; | ||||
| 2620 | $query .= qq{ | ||||
| 2621 | WHERE category = ? | ||||
| 2622 | }; | ||||
| 2623 | $query .= qq{ AND ( branchcode = ? OR branchcode IS NULL )} if $branch_limit; | ||||
| 2624 | $query .= qq{ ORDER BY lib}; | ||||
| 2625 | my $authorised_values_sth = $dbh->prepare( $query ); | ||||
| 2626 | foreach my $tag ( sort keys %{$tagslib} ) { | ||||
| 2627 | my $previous_tag = ''; | ||||
| 2628 | if ( $tag ne '' ) { | ||||
| 2629 | |||||
| 2630 | # loop through each subfield | ||||
| 2631 | my $cntsubf; | ||||
| 2632 | foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) { | ||||
| 2633 | next if ( subfield_is_koha_internal_p($subfield) ); | ||||
| 2634 | next if ( $tagslib->{$tag}->{$subfield}->{'tab'} ne "10" ); | ||||
| 2635 | my %subfield_data; | ||||
| 2636 | $subfield_data{tag} = $tag; | ||||
| 2637 | $subfield_data{subfield} = $subfield; | ||||
| 2638 | $subfield_data{countsubfield} = $cntsubf++; | ||||
| 2639 | $subfield_data{kohafield} = $tagslib->{$tag}->{$subfield}->{'kohafield'}; | ||||
| 2640 | $subfield_data{id} = "tag_".$tag."_subfield_".$subfield."_".int(rand(1000000)); | ||||
| 2641 | |||||
| 2642 | # $subfield_data{marc_lib}=$tagslib->{$tag}->{$subfield}->{lib}; | ||||
| 2643 | $subfield_data{marc_lib} = $tagslib->{$tag}->{$subfield}->{lib}; | ||||
| 2644 | $subfield_data{mandatory} = $tagslib->{$tag}->{$subfield}->{mandatory}; | ||||
| 2645 | $subfield_data{repeatable} = $tagslib->{$tag}->{$subfield}->{repeatable}; | ||||
| 2646 | $subfield_data{hidden} = "display:none" | ||||
| 2647 | if $tagslib->{$tag}->{$subfield}->{hidden}; | ||||
| 2648 | my ( $x, $defaultvalue ); | ||||
| 2649 | if ($itemrecord) { | ||||
| 2650 | ( $x, $defaultvalue ) = _find_value( $tag, $subfield, $itemrecord ); | ||||
| 2651 | } | ||||
| 2652 | $defaultvalue = $tagslib->{$tag}->{$subfield}->{defaultvalue} unless $defaultvalue; | ||||
| 2653 | if ( !defined $defaultvalue ) { | ||||
| 2654 | $defaultvalue = q||; | ||||
| 2655 | } else { | ||||
| 2656 | $defaultvalue =~ s/"/"/g; | ||||
| 2657 | } | ||||
| 2658 | |||||
| 2659 | # search for itemcallnumber if applicable | ||||
| 2660 | if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber' | ||||
| 2661 | && C4::Context->preference('itemcallnumber') ) { | ||||
| 2662 | my $CNtag = substr( C4::Context->preference('itemcallnumber'), 0, 3 ); | ||||
| 2663 | my $CNsubfield = substr( C4::Context->preference('itemcallnumber'), 3, 1 ); | ||||
| 2664 | if ( $itemrecord and my $field = $itemrecord->field($CNtag) ) { | ||||
| 2665 | $defaultvalue = $field->subfield($CNsubfield); | ||||
| 2666 | } | ||||
| 2667 | } | ||||
| 2668 | if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber' | ||||
| 2669 | && $defaultvalues | ||||
| 2670 | && $defaultvalues->{'callnumber'} ) { | ||||
| 2671 | if( $itemrecord and $defaultvalues and not $itemrecord->field($subfield) ){ | ||||
| 2672 | # if the item record exists, only use default value if the item has no callnumber | ||||
| 2673 | $defaultvalue = $defaultvalues->{callnumber}; | ||||
| 2674 | } elsif ( !$itemrecord and $defaultvalues ) { | ||||
| 2675 | # if the item record *doesn't* exists, always use the default value | ||||
| 2676 | $defaultvalue = $defaultvalues->{callnumber}; | ||||
| 2677 | } | ||||
| 2678 | } | ||||
| 2679 | if ( ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.holdingbranch' || $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.homebranch' ) | ||||
| 2680 | && $defaultvalues | ||||
| 2681 | && $defaultvalues->{'branchcode'} ) { | ||||
| 2682 | if ( $itemrecord and $defaultvalues and not $itemrecord->field($subfield) ) { | ||||
| 2683 | $defaultvalue = $defaultvalues->{branchcode}; | ||||
| 2684 | } | ||||
| 2685 | } | ||||
| 2686 | if ( ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.location' ) | ||||
| 2687 | && $defaultvalues | ||||
| 2688 | && $defaultvalues->{'location'} ) { | ||||
| 2689 | |||||
| 2690 | if ( $itemrecord and $defaultvalues and not $itemrecord->field($subfield) ) { | ||||
| 2691 | # if the item record exists, only use default value if the item has no locationr | ||||
| 2692 | $defaultvalue = $defaultvalues->{location}; | ||||
| 2693 | } elsif ( !$itemrecord and $defaultvalues ) { | ||||
| 2694 | # if the item record *doesn't* exists, always use the default value | ||||
| 2695 | $defaultvalue = $defaultvalues->{location}; | ||||
| 2696 | } | ||||
| 2697 | } | ||||
| 2698 | if ( $tagslib->{$tag}->{$subfield}->{authorised_value} ) { | ||||
| 2699 | my @authorised_values; | ||||
| 2700 | my %authorised_lib; | ||||
| 2701 | |||||
| 2702 | # builds list, depending on authorised value... | ||||
| 2703 | #---- branch | ||||
| 2704 | if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) { | ||||
| 2705 | if ( ( C4::Context->preference("IndependantBranches") ) | ||||
| 2706 | && ( C4::Context->userenv->{flags} % 2 != 1 ) ) { | ||||
| 2707 | my $sth = $dbh->prepare( "SELECT branchcode,branchname FROM branches WHERE branchcode = ? ORDER BY branchname" ); | ||||
| 2708 | $sth->execute( C4::Context->userenv->{branch} ); | ||||
| 2709 | push @authorised_values, "" | ||||
| 2710 | unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); | ||||
| 2711 | while ( my ( $branchcode, $branchname ) = $sth->fetchrow_array ) { | ||||
| 2712 | push @authorised_values, $branchcode; | ||||
| 2713 | $authorised_lib{$branchcode} = $branchname; | ||||
| 2714 | } | ||||
| 2715 | } else { | ||||
| 2716 | my $sth = $dbh->prepare( "SELECT branchcode,branchname FROM branches ORDER BY branchname" ); | ||||
| 2717 | $sth->execute; | ||||
| 2718 | push @authorised_values, "" | ||||
| 2719 | unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); | ||||
| 2720 | while ( my ( $branchcode, $branchname ) = $sth->fetchrow_array ) { | ||||
| 2721 | push @authorised_values, $branchcode; | ||||
| 2722 | $authorised_lib{$branchcode} = $branchname; | ||||
| 2723 | } | ||||
| 2724 | } | ||||
| 2725 | |||||
| 2726 | $defaultvalue = C4::Context->userenv->{branch}; | ||||
| 2727 | if ( $defaultvalues and $defaultvalues->{branchcode} ) { | ||||
| 2728 | $defaultvalue = $defaultvalues->{branchcode}; | ||||
| 2729 | } | ||||
| 2730 | |||||
| 2731 | #----- itemtypes | ||||
| 2732 | } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { | ||||
| 2733 | my $sth = $dbh->prepare( "SELECT itemtype,description FROM itemtypes ORDER BY description" ); | ||||
| 2734 | $sth->execute; | ||||
| 2735 | push @authorised_values, "" | ||||
| 2736 | unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); | ||||
| 2737 | while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { | ||||
| 2738 | push @authorised_values, $itemtype; | ||||
| 2739 | $authorised_lib{$itemtype} = $description; | ||||
| 2740 | } | ||||
| 2741 | #---- class_sources | ||||
| 2742 | } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "cn_source" ) { | ||||
| 2743 | push @authorised_values, "" unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); | ||||
| 2744 | |||||
| 2745 | my $class_sources = GetClassSources(); | ||||
| 2746 | my $default_source = C4::Context->preference("DefaultClassificationSource"); | ||||
| 2747 | |||||
| 2748 | foreach my $class_source (sort keys %$class_sources) { | ||||
| 2749 | next unless $class_sources->{$class_source}->{'used'} or | ||||
| 2750 | ($class_source eq $default_source); | ||||
| 2751 | push @authorised_values, $class_source; | ||||
| 2752 | $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'}; | ||||
| 2753 | } | ||||
| 2754 | |||||
| 2755 | $defaultvalue = $default_source; | ||||
| 2756 | |||||
| 2757 | #---- "true" authorised value | ||||
| 2758 | } else { | ||||
| 2759 | $authorised_values_sth->execute( | ||||
| 2760 | $tagslib->{$tag}->{$subfield}->{authorised_value}, | ||||
| 2761 | $branch_limit ? $branch_limit : () | ||||
| 2762 | ); | ||||
| 2763 | push @authorised_values, "" | ||||
| 2764 | unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); | ||||
| 2765 | while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) { | ||||
| 2766 | push @authorised_values, $value; | ||||
| 2767 | $authorised_lib{$value} = $lib; | ||||
| 2768 | } | ||||
| 2769 | } | ||||
| 2770 | $subfield_data{marc_value} = CGI::scrolling_list( | ||||
| 2771 | -name => 'field_value', | ||||
| 2772 | -values => \@authorised_values, | ||||
| 2773 | -default => "$defaultvalue", | ||||
| 2774 | -labels => \%authorised_lib, | ||||
| 2775 | -size => 1, | ||||
| 2776 | -tabindex => '', | ||||
| 2777 | -multiple => 0, | ||||
| 2778 | ); | ||||
| 2779 | } elsif ( $tagslib->{$tag}->{$subfield}->{value_builder} ) { | ||||
| 2780 | # opening plugin | ||||
| 2781 | my $plugin = C4::Context->intranetdir . "/cataloguing/value_builder/" . $tagslib->{$tag}->{$subfield}->{'value_builder'}; | ||||
| 2782 | if (do $plugin) { | ||||
| 2783 | my $extended_param = plugin_parameters( $dbh, undef, $tagslib, $subfield_data{id}, undef ); | ||||
| 2784 | my ( $function_name, $javascript ) = plugin_javascript( $dbh, undef, $tagslib, $subfield_data{id}, undef ); | ||||
| 2785 | $subfield_data{random} = int(rand(1000000)); # why do we need 2 different randoms? | ||||
| 2786 | $subfield_data{marc_value} = qq[<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" | ||||
| 2787 | onfocus="Focus$function_name($subfield_data{random}, '$subfield_data{id}');" | ||||
| 2788 | onblur=" Blur$function_name($subfield_data{random}, '$subfield_data{id}');" /> | ||||
| 2789 | <a href="#" class="buttonDot" onclick="Clic$function_name('$subfield_data{id}'); return false;" title="Tag Editor">...</a> | ||||
| 2790 | $javascript]; | ||||
| 2791 | } else { | ||||
| 2792 | warn "Plugin Failed: $plugin"; | ||||
| 2793 | $subfield_data{marc_value} = qq(<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" />); # supply default input form | ||||
| 2794 | } | ||||
| 2795 | } | ||||
| 2796 | elsif ( $tag eq '' ) { # it's an hidden field | ||||
| 2797 | $subfield_data{marc_value} = qq(<input type="hidden" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />); | ||||
| 2798 | } | ||||
| 2799 | elsif ( $tagslib->{$tag}->{$subfield}->{'hidden'} ) { # FIXME: shouldn't input type be "hidden" ? | ||||
| 2800 | $subfield_data{marc_value} = qq(<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />); | ||||
| 2801 | } | ||||
| 2802 | elsif ( length($defaultvalue) > 100 | ||||
| 2803 | or (C4::Context->preference("marcflavour") eq "UNIMARC" and | ||||
| 2804 | 300 <= $tag && $tag < 400 && $subfield eq 'a' ) | ||||
| 2805 | or (C4::Context->preference("marcflavour") eq "MARC21" and | ||||
| 2806 | 500 <= $tag && $tag < 600 ) | ||||
| 2807 | ) { | ||||
| 2808 | # oversize field (textarea) | ||||
| 2809 | $subfield_data{marc_value} = qq(<textarea tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255">$defaultvalue</textarea>\n"); | ||||
| 2810 | } else { | ||||
| 2811 | $subfield_data{marc_value} = "<input type=\"text\" name=\"field_value\" value=\"$defaultvalue\" size=\"50\" maxlength=\"255\" />"; | ||||
| 2812 | } | ||||
| 2813 | push( @loop_data, \%subfield_data ); | ||||
| 2814 | } | ||||
| 2815 | } | ||||
| 2816 | } | ||||
| 2817 | my $itemnumber; | ||||
| 2818 | if ( $itemrecord && $itemrecord->field($itemtagfield) ) { | ||||
| 2819 | $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield ); | ||||
| 2820 | } | ||||
| 2821 | return { | ||||
| 2822 | 'itemtagfield' => $itemtagfield, | ||||
| 2823 | 'itemtagsubfield' => $itemtagsubfield, | ||||
| 2824 | 'itemnumber' => $itemnumber, | ||||
| 2825 | 'iteminformation' => \@loop_data | ||||
| 2826 | }; | ||||
| 2827 | } | ||||
| 2828 | |||||
| 2829 | 1 | 12µs | 1; |