View | Details | Raw Unified | Return to bug 20271
Collapse All | Expand All

(-)a/C4/Items.pm (-165 / +163 lines)
Lines 50-56 use vars qw(@ISA @EXPORT); Link Here
50
50
51
BEGIN {
51
BEGIN {
52
52
53
	require Exporter;
53
    require Exporter;
54
    @ISA = qw( Exporter );
54
    @ISA = qw( Exporter );
55
55
56
    # function exports
56
    # function exports
Lines 60-92 BEGIN { Link Here
60
        AddItem
60
        AddItem
61
        AddItemBatchFromMarc
61
        AddItemBatchFromMarc
62
        ModItemFromMarc
62
        ModItemFromMarc
63
    Item2Marc
63
        Item2Marc
64
        ModItem
64
        ModItem
65
        ModDateLastSeen
65
        ModDateLastSeen
66
        ModItemTransfer
66
        ModItemTransfer
67
        DelItem
67
        DelItem
68
    
68
69
        CheckItemPreSave
69
        CheckItemPreSave
70
    
70
71
        GetItemsForInventory
71
        GetItemsForInventory
72
        GetItemsByBiblioitemnumber
72
        GetItemsByBiblioitemnumber
73
        GetItemsInfo
73
        GetItemsInfo
74
	GetItemsLocationInfo
74
        GetItemsLocationInfo
75
	GetHostItemsInfo
75
        GetHostItemsInfo
76
        GetItemnumbersForBiblio
76
        GetItemnumbersForBiblio
77
	get_hostitemnumbers_of
77
        get_hostitemnumbers_of
78
        GetItemnumberFromBarcode
78
        GetItemnumberFromBarcode
79
        GetBarcodeFromItemnumber
79
        GetBarcodeFromItemnumber
80
        GetHiddenItemnumbers
80
        GetHiddenItemnumbers
81
        ItemSafeToDelete
81
        ItemSafeToDelete
82
        DelItemCheck
82
        DelItemCheck
83
    MoveItemFromBiblio
83
        MoveItemFromBiblio
84
    GetLatestAcquisitions
84
        GetLatestAcquisitions
85
85
86
        CartToShelf
86
        CartToShelf
87
        ShelfToCart
87
        ShelfToCart
88
88
89
	GetAnalyticsCount
89
        GetAnalyticsCount
90
90
91
        SearchItemsByField
91
        SearchItemsByField
92
        SearchItems
92
        SearchItems
Lines 102-108 C4::Items - item management functions Link Here
102
102
103
=head1 DESCRIPTION
103
=head1 DESCRIPTION
104
104
105
This module contains an API for manipulating item 
105
This module contains an API for manipulating item
106
records in Koha, and is used by cataloguing, circulation,
106
records in Koha, and is used by cataloguing, circulation,
107
acquisitions, and serials management.
107
acquisitions, and serials management.
108
108
Lines 116-122 modification transaction must keep the items table Link Here
116
and the MARC XML in sync at all times.
116
and the MARC XML in sync at all times.
117
117
118
Consequently, all code that creates, modifies, or deletes
118
Consequently, all code that creates, modifies, or deletes
119
item records B<must> use an appropriate function from 
119
item records B<must> use an appropriate function from
120
C<C4::Items>.  If no existing function is suitable, it is
120
C<C4::Items>.  If no existing function is suitable, it is
121
better to add one to C<C4::Items> than to use add
121
better to add one to C<C4::Items> than to use add
122
one-off SQL statements to add or modify items.
122
one-off SQL statements to add or modify items.
Lines 222-228 sub ShelfToCart { Link Here
222
222
223
=head2 AddItemFromMarc
223
=head2 AddItemFromMarc
224
224
225
  my ($biblionumber, $biblioitemnumber, $itemnumber) 
225
  my ($biblionumber, $biblioitemnumber, $itemnumber)
226
      = AddItemFromMarc($source_item_marc, $biblionumber);
226
      = AddItemFromMarc($source_item_marc, $biblionumber);
227
227
228
Given a MARC::Record object containing an embedded item
228
Given a MARC::Record object containing an embedded item
Lines 237-245 sub AddItemFromMarc { Link Here
237
    # parse item hash from MARC
237
    # parse item hash from MARC
238
    my $frameworkcode = C4::Biblio::GetFrameworkCode( $biblionumber );
238
    my $frameworkcode = C4::Biblio::GetFrameworkCode( $biblionumber );
239
    my ($itemtag,$itemsubfield)=C4::Biblio::GetMarcFromKohaField("items.itemnumber",$frameworkcode);
239
    my ($itemtag,$itemsubfield)=C4::Biblio::GetMarcFromKohaField("items.itemnumber",$frameworkcode);
240
	
240
241
	my $localitemmarc=MARC::Record->new;
241
    my $localitemmarc=MARC::Record->new;
242
	$localitemmarc->append_fields($source_item_marc->field($itemtag));
242
    $localitemmarc->append_fields($source_item_marc->field($itemtag));
243
    my $item = &TransformMarcToKoha( $localitemmarc, $frameworkcode ,'items');
243
    my $item = &TransformMarcToKoha( $localitemmarc, $frameworkcode ,'items');
244
    my $unlinked_item_subfields = _get_unlinked_item_subfields($localitemmarc, $frameworkcode);
244
    my $unlinked_item_subfields = _get_unlinked_item_subfields($localitemmarc, $frameworkcode);
245
    return AddItem($item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields);
245
    return AddItem($item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields);
Lines 247-253 sub AddItemFromMarc { Link Here
247
247
248
=head2 AddItem
248
=head2 AddItem
249
249
250
  my ($biblionumber, $biblioitemnumber, $itemnumber) 
250
  my ($biblionumber, $biblioitemnumber, $itemnumber)
251
      = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields]);
251
      = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields]);
252
252
253
Given a hash containing item column names as keys,
253
Given a hash containing item column names as keys,
Lines 261-267 The final optional parameter, C<$unlinked_item_subfields>, contains Link Here
261
an arrayref containing subfields present in the original MARC
261
an arrayref containing subfields present in the original MARC
262
representation of the item (e.g., from the item editor) that are
262
representation of the item (e.g., from the item editor) that are
263
not mapped to C<items> columns directly but should instead
263
not mapped to C<items> columns directly but should instead
264
be stored in C<items.more_subfields_xml> and included in 
264
be stored in C<items.more_subfields_xml> and included in
265
the biblio items tag for display and indexing.
265
the biblio items tag for display and indexing.
266
266
267
=cut
267
=cut
Lines 309-315 sub AddItem { Link Here
309
309
310
=head2 AddItemBatchFromMarc
310
=head2 AddItemBatchFromMarc
311
311
312
  ($itemnumber_ref, $error_ref) = AddItemBatchFromMarc($record, 
312
  ($itemnumber_ref, $error_ref) = AddItemBatchFromMarc($record,
313
             $biblionumber, $biblioitemnumber, $frameworkcode);
313
             $biblionumber, $biblioitemnumber, $frameworkcode);
314
314
315
Efficiently create item records from a MARC biblio record with
315
Efficiently create item records from a MARC biblio record with
Lines 374-380 sub AddItemBatchFromMarc { Link Here
374
        # and there is no TransformMarcFieldToKoha
374
        # and there is no TransformMarcFieldToKoha
375
        my $temp_item_marc = MARC::Record->new();
375
        my $temp_item_marc = MARC::Record->new();
376
        $temp_item_marc->append_fields($item_field);
376
        $temp_item_marc->append_fields($item_field);
377
    
377
378
        # add biblionumber and biblioitemnumber
378
        # add biblionumber and biblioitemnumber
379
        my $item = TransformMarcToKoha( $temp_item_marc, $frameworkcode, 'items' );
379
        my $item = TransformMarcToKoha( $temp_item_marc, $frameworkcode, 'items' );
380
        my $unlinked_item_subfields = _get_unlinked_item_subfields($temp_item_marc, $frameworkcode);
380
        my $unlinked_item_subfields = _get_unlinked_item_subfields($temp_item_marc, $frameworkcode);
Lines 397-403 sub AddItemBatchFromMarc { Link Here
397
        push @itemnumbers, $itemnumber; # FIXME not checking error
397
        push @itemnumbers, $itemnumber; # FIXME not checking error
398
        $item->{'itemnumber'} = $itemnumber;
398
        $item->{'itemnumber'} = $itemnumber;
399
399
400
        logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog"); 
400
        logaction("CATALOGUING", "ADD", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
401
401
402
        my $new_item_marc = _marc_from_item_hash($item, $frameworkcode, $unlinked_item_subfields);
402
        my $new_item_marc = _marc_from_item_hash($item, $frameworkcode, $unlinked_item_subfields);
403
        $item_field->replace_with($new_item_marc->field($itemtag));
403
        $item_field->replace_with($new_item_marc->field($itemtag));
Lines 420-426 sub AddItemBatchFromMarc { Link Here
420
420
421
This function updates an item record based on a supplied
421
This function updates an item record based on a supplied
422
C<MARC::Record> object containing an embedded item field.
422
C<MARC::Record> object containing an embedded item field.
423
This API is meant for the use of C<additem.pl>; for 
423
This API is meant for the use of C<additem.pl>; for
424
other purposes, C<ModItem> should be used.
424
other purposes, C<ModItem> should be used.
425
425
426
This function uses the hash %default_values_for_mod_from_marc,
426
This function uses the hash %default_values_for_mod_from_marc,
Lines 539-549 C<$unlinked_item_subfields> contains an arrayref containing Link Here
539
subfields present in the original MARC
539
subfields present in the original MARC
540
representation of the item (e.g., from the item editor) that are
540
representation of the item (e.g., from the item editor) that are
541
not mapped to C<items> columns directly but should instead
541
not mapped to C<items> columns directly but should instead
542
be stored in C<items.more_subfields_xml> and included in 
542
be stored in C<items.more_subfields_xml> and included in
543
the biblio items tag for display and indexing.
543
the biblio items tag for display and indexing.
544
544
545
If one of the changed columns is used to calculate
545
If one of the changed columns is used to calculate
546
the derived value of a column such as C<items.cn_sort>, 
546
the derived value of a column such as C<items.cn_sort>,
547
this routine will perform the necessary calculation
547
this routine will perform the necessary calculation
548
and set the value.
548
and set the value.
549
549
Lines 771-777 sub CheckItemPreSave { Link Here
771
771
772
=head1 EXPORTED SPECIAL ACCESSOR FUNCTIONS
772
=head1 EXPORTED SPECIAL ACCESSOR FUNCTIONS
773
773
774
The following functions provide various ways of 
774
The following functions provide various ways of
775
getting an item record, a set of item records, or
775
getting an item record, a set of item records, or
776
lists of authorized values for certain item fields.
776
lists of authorized values for certain item fields.
777
777
Lines 948-956 sub GetItemsByBiblioitemnumber { Link Here
948
    my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ? AND items.deleted_at IS NULL") || die $dbh->errstr;
948
    my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ? AND items.deleted_at IS NULL") || die $dbh->errstr;
949
    # Get all items attached to a biblioitem
949
    # Get all items attached to a biblioitem
950
    my $i = 0;
950
    my $i = 0;
951
    my @results; 
951
    my @results;
952
    $sth->execute($bibitem) || die $sth->errstr;
952
    $sth->execute($bibitem) || die $sth->errstr;
953
    while ( my $data = $sth->fetchrow_hashref ) {  
953
    while ( my $data = $sth->fetchrow_hashref ) {
954
        # Foreach item, get circulation information
954
        # Foreach item, get circulation information
955
        my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers
955
        my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers
956
                                   WHERE itemnumber = ?
956
                                   WHERE itemnumber = ?
Lines 965-973 sub GetItemsByBiblioitemnumber { Link Here
965
        }
965
        }
966
        else {
966
        else {
967
            # set date_due to blank, so in the template we check itemlost, and withdrawn
967
            # set date_due to blank, so in the template we check itemlost, and withdrawn
968
            $data->{'date_due'} = '';                                                                                                         
968
            $data->{'date_due'} = '';
969
        }    # else         
969
        }    # else
970
        # Find the last 3 people who borrowed this item.                  
970
        # Find the last 3 people who borrowed this item.
971
        my $query2 = "SELECT * FROM old_issues, borrowers WHERE itemnumber = ?
971
        my $query2 = "SELECT * FROM old_issues, borrowers WHERE itemnumber = ?
972
                      AND old_issues.borrowernumber = borrowers.borrowernumber
972
                      AND old_issues.borrowernumber = borrowers.borrowernumber
973
                      ORDER BY returndate desc,timestamp desc LIMIT 3";
973
                      ORDER BY returndate desc,timestamp desc LIMIT 3";
Lines 981-988 sub GetItemsByBiblioitemnumber { Link Here
981
            $i2++;
981
            $i2++;
982
        }
982
        }
983
        push(@results,$data);
983
        push(@results,$data);
984
    } 
984
    }
985
    return (\@results); 
985
    return (\@results);
986
}
986
}
987
987
988
=head2 GetItemsInfo
988
=head2 GetItemsInfo
Lines 1066-1086 sub GetItemsInfo { Link Here
1066
           home.opac_info as home_branch_opac_info
1066
           home.opac_info as home_branch_opac_info
1067
    ";
1067
    ";
1068
    $query .= "
1068
    $query .= "
1069
     FROM items
1069
        FROM items
1070
     LEFT JOIN branches AS holding ON items.holdingbranch = holding.branchcode
1070
        LEFT JOIN branches AS holding ON items.holdingbranch = holding.branchcode
1071
     LEFT JOIN branches AS home ON items.homebranch=home.branchcode
1071
        LEFT JOIN branches AS home ON items.homebranch=home.branchcode
1072
     LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber AND biblio.deleted_at IS NULL
1072
        LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber AND biblio.deleted_at IS NULL
1073
     LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
1073
        LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
1074
     LEFT JOIN issues USING (itemnumber)
1074
        LEFT JOIN issues USING (itemnumber)
1075
     LEFT JOIN borrowers USING (borrowernumber)
1075
        LEFT JOIN borrowers USING (borrowernumber)
1076
     LEFT JOIN serialitems USING (itemnumber)
1076
        LEFT JOIN serialitems USING (itemnumber)
1077
     LEFT JOIN serial USING (serialid)
1077
        LEFT JOIN serial USING (serialid)
1078
     LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
1078
        LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
1079
     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
1079
     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
1080
    $query .= q|
1080
    $query .= q|
1081
    LEFT JOIN localization ON itemtypes.itemtype = localization.code
1081
        LEFT JOIN localization ON itemtypes.itemtype = localization.code
1082
        AND localization.entity = 'itemtypes'
1082
            AND localization.entity = 'itemtypes'
1083
        AND localization.lang = ?
1083
            AND localization.lang = ?
1084
    |;
1084
    |;
1085
1085
1086
    $query .= " WHERE items.biblionumber = ? AND items.deleted_at IS NULL ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
1086
    $query .= " WHERE items.biblionumber = ? AND items.deleted_at IS NULL ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
Lines 1166-1172 The intranet description for the Shelving Location as set in authorised_values ' Link Here
1166
1166
1167
=item C<$data-E<gt>{location_opac}>
1167
=item C<$data-E<gt>{location_opac}>
1168
1168
1169
The OPAC description for the Shelving Location as set in authorised_values 'LOC'.  Falls back to intranet description if no OPAC 
1169
The OPAC description for the Shelving Location as set in authorised_values 'LOC'.  Falls back to intranet description if no OPAC
1170
description is set.
1170
description is set.
1171
1171
1172
=item C<$data-E<gt>{itemcallnumber}>
1172
=item C<$data-E<gt>{itemcallnumber}>
Lines 1178-1198 Item's itemcallnumber Link Here
1178
Item's call number normalized for sorting
1178
Item's call number normalized for sorting
1179
1179
1180
=back
1180
=back
1181
  
1181
1182
=cut
1182
=cut
1183
1183
1184
sub GetItemsLocationInfo {
1184
sub GetItemsLocationInfo {
1185
        my $biblionumber = shift;
1185
        my $biblionumber = shift;
1186
        my @results;
1186
        my @results;
1187
1187
1188
	my $dbh = C4::Context->dbh;
1188
    my $dbh = C4::Context->dbh;
1189
	my $query = "SELECT a.branchname as homebranch, b.branchname as holdingbranch, 
1189
    my $query = "SELECT a.branchname as homebranch, b.branchname as holdingbranch,
1190
			    location, itemcallnumber, cn_sort
1190
                location, itemcallnumber, cn_sort
1191
		     FROM items, branches as a, branches as b
1191
                FROM items, branches as a, branches as b
1192
		     WHERE homebranch = a.branchcode AND holdingbranch = b.branchcode 
1192
                WHERE homebranch = a.branchcode AND holdingbranch = b.branchcode
1193
		     AND biblionumber = ? AND deleted_at IS NULL
1193
                AND biblionumber = ? AND deleted_at IS NULL
1194
		     ORDER BY cn_sort ASC";
1194
                ORDER BY cn_sort ASC";
1195
	my $sth = $dbh->prepare($query);
1195
    my $sth = $dbh->prepare($query);
1196
        $sth->execute($biblionumber);
1196
        $sth->execute($biblionumber);
1197
1197
1198
        while ( my $data = $sth->fetchrow_hashref ) {
1198
        while ( my $data = $sth->fetchrow_hashref ) {
Lines 1200-1300 sub GetItemsLocationInfo { Link Here
1200
             $av = $av->count ? $av->next : undef;
1200
             $av = $av->count ? $av->next : undef;
1201
             $data->{location_intranet} = $av ? $av->lib : '';
1201
             $data->{location_intranet} = $av ? $av->lib : '';
1202
             $data->{location_opac}     = $av ? $av->opac_description : '';
1202
             $data->{location_opac}     = $av ? $av->opac_description : '';
1203
	     push @results, $data;
1203
         push @results, $data;
1204
	}
1204
    }
1205
	return @results;
1205
    return @results;
1206
}
1206
}
1207
1207
1208
=head2 GetHostItemsInfo
1208
=head2 GetHostItemsInfo
1209
1209
1210
	$hostiteminfo = GetHostItemsInfo($hostfield);
1210
    $hostiteminfo = GetHostItemsInfo($hostfield);
1211
	Returns the iteminfo for items linked to records via a host field
1211
    Returns the iteminfo for items linked to records via a host field
1212
1212
1213
=cut
1213
=cut
1214
1214
1215
sub GetHostItemsInfo {
1215
sub GetHostItemsInfo {
1216
	my ($record) = @_;
1216
    my ($record) = @_;
1217
	my @returnitemsInfo;
1217
    my @returnitemsInfo;
1218
1218
1219
	if (C4::Context->preference('marcflavour') eq 'MARC21' ||
1219
    if (C4::Context->preference('marcflavour') eq 'MARC21' ||
1220
        C4::Context->preference('marcflavour') eq 'NORMARC'){
1220
        C4::Context->preference('marcflavour') eq 'NORMARC'){
1221
	    foreach my $hostfield ( $record->field('773') ) {
1221
        foreach my $hostfield ( $record->field('773') ) {
1222
        	my $hostbiblionumber = $hostfield->subfield("0");
1222
            my $hostbiblionumber = $hostfield->subfield("0");
1223
	        my $linkeditemnumber = $hostfield->subfield("9");
1223
            my $linkeditemnumber = $hostfield->subfield("9");
1224
        	my @hostitemInfos = GetItemsInfo($hostbiblionumber);
1224
            my @hostitemInfos = GetItemsInfo($hostbiblionumber);
1225
	        foreach my $hostitemInfo (@hostitemInfos){
1225
            foreach my $hostitemInfo (@hostitemInfos){
1226
        	        if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){
1226
                    if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){
1227
                	        push (@returnitemsInfo,$hostitemInfo);
1227
                            push (@returnitemsInfo,$hostitemInfo);
1228
				last;
1228
                last;
1229
                	}
1229
                    }
1230
        	}
1230
            }
1231
	    }
1231
        }
1232
	} elsif ( C4::Context->preference('marcflavour') eq 'UNIMARC'){
1232
    } elsif ( C4::Context->preference('marcflavour') eq 'UNIMARC'){
1233
	    foreach my $hostfield ( $record->field('461') ) {
1233
        foreach my $hostfield ( $record->field('461') ) {
1234
        	my $hostbiblionumber = $hostfield->subfield("0");
1234
            my $hostbiblionumber = $hostfield->subfield("0");
1235
	        my $linkeditemnumber = $hostfield->subfield("9");
1235
            my $linkeditemnumber = $hostfield->subfield("9");
1236
        	my @hostitemInfos = GetItemsInfo($hostbiblionumber);
1236
            my @hostitemInfos = GetItemsInfo($hostbiblionumber);
1237
	        foreach my $hostitemInfo (@hostitemInfos){
1237
            foreach my $hostitemInfo (@hostitemInfos){
1238
        	        if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){
1238
                    if ($hostitemInfo->{itemnumber} eq $linkeditemnumber){
1239
                	        push (@returnitemsInfo,$hostitemInfo);
1239
                            push (@returnitemsInfo,$hostitemInfo);
1240
				last;
1240
                last;
1241
                	}
1241
                    }
1242
        	}
1242
            }
1243
	    }
1243
        }
1244
	}
1244
    }
1245
	return @returnitemsInfo;
1245
    return @returnitemsInfo;
1246
}
1246
}
1247
1247
1248
1248
1249
=head2 GetLastAcquisitions
1249
=head2 GetLastAcquisitions
1250
1250
1251
  my $lastacq = GetLastAcquisitions({'branches' => ('branch1','branch2'), 
1251
  my $lastacq = GetLastAcquisitions({'branches' => ('branch1','branch2'),
1252
                                    'itemtypes' => ('BK','BD')}, 10);
1252
                                    'itemtypes' => ('BK','BD')}, 10);
1253
1253
1254
=cut
1254
=cut
1255
1255
1256
sub  GetLastAcquisitions {
1256
sub  GetLastAcquisitions {
1257
	my ($data,$max) = @_;
1257
    my ($data,$max) = @_;
1258
1258
1259
	my $itemtype = C4::Context->preference('item-level_itypes') ? 'itype' : 'itemtype';
1259
    my $itemtype = C4::Context->preference('item-level_itypes') ? 'itype' : 'itemtype';
1260
	
1260
1261
	my $number_of_branches = @{$data->{branches}};
1261
    my $number_of_branches = @{$data->{branches}};
1262
	my $number_of_itemtypes   = @{$data->{itemtypes}};
1262
    my $number_of_itemtypes   = @{$data->{itemtypes}};
1263
	
1263
1264
	
1264
    my @where = ('WHERE (items.deleted_at IS NULL AND biblio.deleted_at IS NULL AND biblioitems.deleted_at IS NULL)');
1265
	my @where = ('WHERE (items.deleted_at IS NULL AND biblio.deleted_at IS NULL AND biblioitems.deleted_at IS NULL) ');
1265
    $number_of_branches and push @where
1266
	$number_of_branches and push @where
1266
       , 'AND holdingbranch IN ('
1267
	   , 'AND holdingbranch IN (' 
1267
       , join(',', ('?') x $number_of_branches )
1268
	   , join(',', ('?') x $number_of_branches )
1268
       , ')'
1269
	   , ')'
1269
     ;
1270
	 ;
1270
1271
	
1271
    $number_of_itemtypes and push @where
1272
	$number_of_itemtypes and push @where
1272
       , "AND $itemtype IN ("
1273
	   , "AND $itemtype IN (" 
1273
       , join(',', ('?') x $number_of_itemtypes )
1274
	   , join(',', ('?') x $number_of_itemtypes )
1274
       , ')'
1275
	   , ')'
1275
     ;
1276
	 ;
1276
1277
1277
    my $query = "SELECT biblio.biblionumber as biblionumber, title, dateaccessioned
1278
	my $query = "SELECT biblio.biblionumber as biblionumber, title, dateaccessioned
1278
                 FROM items RIGHT JOIN biblio ON (items.biblionumber=biblio.biblionumber)
1279
				 FROM items RIGHT JOIN biblio ON (items.biblionumber=biblio.biblionumber) 
1279
                 RIGHT JOIN biblioitems ON (items.biblioitemnumber=biblioitems.biblioitemnumber)
1280
			            RIGHT JOIN biblioitems ON (items.biblioitemnumber=biblioitems.biblioitemnumber)
1280
                 @where
1281
			            @where
1281
                 GROUP BY biblio.biblionumber
1282
			            GROUP BY biblio.biblionumber 
1282
                 ORDER BY dateaccessioned DESC LIMIT $max";
1283
			            ORDER BY dateaccessioned DESC LIMIT $max";
1283
1284
1284
    my $dbh = C4::Context->dbh;
1285
	my $dbh = C4::Context->dbh;
1285
    my $sth = $dbh->prepare($query);
1286
	my $sth = $dbh->prepare($query);
1286
1287
    
1288
    $sth->execute((@{$data->{branches}}, @{$data->{itemtypes}}));
1287
    $sth->execute((@{$data->{branches}}, @{$data->{itemtypes}}));
1289
	
1288
1290
	my @results;
1289
    my @results;
1291
	while( my $row = $sth->fetchrow_hashref){
1290
    while( my $row = $sth->fetchrow_hashref){
1292
		push @results, {date => $row->{dateaccessioned} 
1291
        push @results, {date => $row->{dateaccessioned}
1293
						, biblionumber => $row->{biblionumber}
1292
                        , biblionumber => $row->{biblionumber}
1294
						, title => $row->{title}};
1293
                        , title => $row->{title}};
1295
	}
1294
    }
1296
	
1295
1297
	return @results;
1296
    return @results;
1298
}
1297
}
1299
1298
1300
=head2 GetItemnumbersForBiblio
1299
=head2 GetItemnumbersForBiblio
Lines 1497-1512 sub GetMarcItem { Link Here
1497
    # Tack on 'items.' prefix to column names so that C4::Biblio::TransformKohaToMarc will work.
1496
    # Tack on 'items.' prefix to column names so that C4::Biblio::TransformKohaToMarc will work.
1498
    # Also, don't emit a subfield if the underlying field is blank.
1497
    # Also, don't emit a subfield if the underlying field is blank.
1499
1498
1500
    
1499
1501
    return Item2Marc($itemrecord,$biblionumber);
1500
    return Item2Marc($itemrecord,$biblionumber);
1502
1501
1503
}
1502
}
1504
sub Item2Marc {
1503
sub Item2Marc {
1505
	my ($itemrecord,$biblionumber)=@_;
1504
    my ($itemrecord,$biblionumber)=@_;
1506
    my $mungeditem = { 
1505
    my $mungeditem = {
1507
        map {  
1506
        map {
1508
            defined($itemrecord->{$_}) && $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()  
1507
            defined($itemrecord->{$_}) && $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()
1509
        } keys %{ $itemrecord } 
1508
        } keys %{ $itemrecord }
1510
    };
1509
    };
1511
    my $framework = C4::Biblio::GetFrameworkCode( $biblionumber );
1510
    my $framework = C4::Biblio::GetFrameworkCode( $biblionumber );
1512
    my $itemmarc = C4::Biblio::TransformKohaToMarc(
1511
    my $itemmarc = C4::Biblio::TransformKohaToMarc(
Lines 1518-1528 sub Item2Marc { Link Here
1518
1517
1519
    my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'});
1518
    my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'});
1520
    if (defined $unlinked_item_subfields and $#$unlinked_item_subfields > -1) {
1519
    if (defined $unlinked_item_subfields and $#$unlinked_item_subfields > -1) {
1521
		foreach my $field ($itemmarc->field($itemtag)){
1520
        foreach my $field ($itemmarc->field($itemtag)){
1522
            $field->add_subfields(@$unlinked_item_subfields);
1521
            $field->add_subfields(@$unlinked_item_subfields);
1523
        }
1522
        }
1524
    }
1523
    }
1525
	return $itemmarc;
1524
    return $itemmarc;
1526
}
1525
}
1527
1526
1528
=head1 PRIVATE FUNCTIONS AND VARIABLES
1527
=head1 PRIVATE FUNCTIONS AND VARIABLES
Lines 1558-1564 my %derived_columns = ( Link Here
1558
    }
1557
    }
1559
);
1558
);
1560
1559
1561
=head2 _set_derived_columns_for_add 
1560
=head2 _set_derived_columns_for_add
1562
1561
1563
  _set_derived_column_for_add($item);
1562
  _set_derived_column_for_add($item);
1564
1563
Lines 1582-1588 sub _set_derived_columns_for_add { Link Here
1582
    }
1581
    }
1583
}
1582
}
1584
1583
1585
=head2 _set_derived_columns_for_mod 
1584
=head2 _set_derived_columns_for_mod
1586
1585
1587
  _set_derived_column_for_mod($item);
1586
  _set_derived_column_for_mod($item);
1588
1587
Lines 1685-1696 row specified by C<$itemnumber>. Link Here
1685
sub _get_single_item_column {
1684
sub _get_single_item_column {
1686
    my $column = shift;
1685
    my $column = shift;
1687
    my $itemnumber = shift;
1686
    my $itemnumber = shift;
1688
    
1687
1689
    my $dbh = C4::Context->dbh;
1688
    my $dbh = C4::Context->dbh;
1690
    my $sth = $dbh->prepare("SELECT $column FROM items WHERE itemnumber = ?");
1689
    my $sth = $dbh->prepare("SELECT $column FROM items WHERE itemnumber = ?");
1691
    $sth->execute($itemnumber);
1690
    $sth->execute($itemnumber);
1692
    my ($value) = $sth->fetchrow();
1691
    my ($value) = $sth->fetchrow();
1693
    return $value; 
1692
    return $value;
1694
}
1693
}
1695
1694
1696
=head2 _calc_items_cn_sort
1695
=head2 _calc_items_cn_sort
Lines 1708-1714 sub _calc_items_cn_sort { Link Here
1708
    $item->{'items.cn_sort'} = GetClassSort($source_values->{'items.cn_source'}, $source_values->{'itemcallnumber'}, "");
1707
    $item->{'items.cn_sort'} = GetClassSort($source_values->{'items.cn_source'}, $source_values->{'itemcallnumber'}, "");
1709
}
1708
}
1710
1709
1711
=head2 _set_defaults_for_add 
1710
=head2 _set_defaults_for_add
1712
1711
1713
  _set_defaults_for_add($item_hash);
1712
  _set_defaults_for_add($item_hash);
1714
1713
Lines 1719-1725 columns: Link Here
1719
1718
1720
=over 2
1719
=over 2
1721
1720
1722
=item * 
1721
=item *
1723
1722
1724
C<items.dateaccessioned>
1723
C<items.dateaccessioned>
1725
1724
Lines 1759-1765 Perform the actual insert into the C<items> table. Link Here
1759
1758
1760
sub _koha_new_item {
1759
sub _koha_new_item {
1761
    my ( $item, $barcode ) = @_;
1760
    my ( $item, $barcode ) = @_;
1762
    my $dbh=C4::Context->dbh;  
1761
    my $dbh=C4::Context->dbh;
1763
    my $error;
1762
    my $error;
1764
    $item->{permanent_location} //= $item->{location};
1763
    $item->{permanent_location} //= $item->{location};
1765
    _mod_item_dates( $item );
1764
    _mod_item_dates( $item );
Lines 1890-1903 sub MoveItemFromBiblio { Link Here
1890
    if ($return == 1) {
1889
    if ($return == 1) {
1891
        ModZebra( $tobiblio, "specialUpdate", "biblioserver" );
1890
        ModZebra( $tobiblio, "specialUpdate", "biblioserver" );
1892
        ModZebra( $frombiblio, "specialUpdate", "biblioserver" );
1891
        ModZebra( $frombiblio, "specialUpdate", "biblioserver" );
1893
	    # Checking if the item we want to move is in an order 
1892
        # Checking if the item we want to move is in an order
1894
        require C4::Acquisition;
1893
        require C4::Acquisition;
1895
        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
1894
        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
1896
	    if ($order) {
1895
        if ($order) {
1897
		    # Replacing the biblionumber within the order if necessary
1896
            # Replacing the biblionumber within the order if necessary
1898
		    $order->{'biblionumber'} = $tobiblio;
1897
            $order->{'biblionumber'} = $tobiblio;
1899
	        C4::Acquisition::ModOrder($order);
1898
            C4::Acquisition::ModOrder($order);
1900
	    }
1899
        }
1901
1900
1902
        # Update reserves, hold_fill_targets, tmp_holdsqueue and linktracker tables
1901
        # Update reserves, hold_fill_targets, tmp_holdsqueue and linktracker tables
1903
        for my $table_name ( qw( reserves hold_fill_targets tmp_holdsqueue linktracker ) ) {
1902
        for my $table_name ( qw( reserves hold_fill_targets tmp_holdsqueue linktracker ) ) {
Lines 1908-1914 sub MoveItemFromBiblio { Link Here
1908
            |, undef, $tobiblio, $itemnumber );
1907
            |, undef, $tobiblio, $itemnumber );
1909
        }
1908
        }
1910
        return $tobiblio;
1909
        return $tobiblio;
1911
	}
1910
    }
1912
    return;
1911
    return;
1913
}
1912
}
1914
1913
Lines 2021-2027 routine accepts a hashref specifying the columns to update. Link Here
2021
2020
2022
sub _koha_modify_item {
2021
sub _koha_modify_item {
2023
    my ( $item ) = @_;
2022
    my ( $item ) = @_;
2024
    my $dbh=C4::Context->dbh;  
2023
    my $dbh=C4::Context->dbh;
2025
    my $error;
2024
    my $error;
2026
2025
2027
    my $query = "UPDATE items SET ";
2026
    my $query = "UPDATE items SET ";
Lines 2112-2123 sub _marc_from_item_hash { Link Here
2112
    if (@_) {
2111
    if (@_) {
2113
        $unlinked_item_subfields = shift;
2112
        $unlinked_item_subfields = shift;
2114
    }
2113
    }
2115
   
2114
2116
    # Tack on 'items.' prefix to column names so lookup from MARC frameworks will work
2115
    # Tack on 'items.' prefix to column names so lookup from MARC frameworks will work
2117
    # Also, don't emit a subfield if the underlying field is blank.
2116
    # Also, don't emit a subfield if the underlying field is blank.
2118
    my $mungeditem = { map {  (defined($item->{$_}) and $item->{$_} ne '') ? 
2117
    my $mungeditem = { map {  (defined($item->{$_}) and $item->{$_} ne '') ?
2119
                                (/^items\./ ? ($_ => $item->{$_}) : ("items.$_" => $item->{$_})) 
2118
                                (/^items\./ ? ($_ => $item->{$_}) : ("items.$_" => $item->{$_}))
2120
                                : ()  } keys %{ $item } }; 
2119
                                : ()  } keys %{ $item } };
2121
2120
2122
    my $item_marc = MARC::Record->new();
2121
    my $item_marc = MARC::Record->new();
2123
    foreach my $item_field ( keys %{$mungeditem} ) {
2122
    foreach my $item_field ( keys %{$mungeditem} ) {
Lines 2161-2167 sub _repack_item_errors { Link Here
2161
        $repacked_error->{'error_code'} = $error_code;
2160
        $repacked_error->{'error_code'} = $error_code;
2162
        $repacked_error->{'error_information'} = $error_ref->{$error_code};
2161
        $repacked_error->{'error_information'} = $error_ref->{$error_code};
2163
        push @repacked_errors, $repacked_error;
2162
        push @repacked_errors, $repacked_error;
2164
    } 
2163
    }
2165
2164
2166
    return @repacked_errors;
2165
    return @repacked_errors;
2167
}
2166
}
Lines 2184-2190 sub _get_unlinked_item_subfields { Link Here
2184
    my @fields = $original_item_marc->fields();
2183
    my @fields = $original_item_marc->fields();
2185
    if ($#fields > -1) {
2184
    if ($#fields > -1) {
2186
        my $field = $fields[0];
2185
        my $field = $fields[0];
2187
	    my $tag = $field->tag();
2186
        my $tag = $field->tag();
2188
        foreach my $subfield ($field->subfields()) {
2187
        foreach my $subfield ($field->subfields()) {
2189
            if (defined $subfield->[1] and
2188
            if (defined $subfield->[1] and
2190
                $subfield->[1] ne '' and
2189
                $subfield->[1] ne '' and
Lines 2211-2217 sub _get_unlinked_subfields_xml { Link Here
2211
        # use of tag 999 is arbitrary, and doesn't need to match the item tag
2210
        # use of tag 999 is arbitrary, and doesn't need to match the item tag
2212
        # used in the framework
2211
        # used in the framework
2213
        $marc->append_fields(MARC::Field->new('999', ' ', ' ', @$unlinked_item_subfields));
2212
        $marc->append_fields(MARC::Field->new('999', ' ', ' ', @$unlinked_item_subfields));
2214
        $marc->encoding("UTF-8");    
2213
        $marc->encoding("UTF-8");
2215
        $xml = $marc->as_xml("USMARC");
2214
        $xml = $marc->as_xml("USMARC");
2216
    }
2215
    }
2217
2216
Lines 2243-2249 sub _parse_unlinked_item_subfields_from_xml { Link Here
2243
2242
2244
  $count= &GetAnalyticsCount($itemnumber)
2243
  $count= &GetAnalyticsCount($itemnumber)
2245
2244
2246
counts Usage of itemnumber in Analytical bibliorecords. 
2245
counts Usage of itemnumber in Analytical bibliorecords.
2247
2246
2248
=cut
2247
=cut
2249
2248
Lines 2447-2456 sub SearchItems { Link Here
2447
    my $query = q{
2446
    my $query = q{
2448
        SELECT SQL_CALC_FOUND_ROWS items.*
2447
        SELECT SQL_CALC_FOUND_ROWS items.*
2449
        FROM items
2448
        FROM items
2450
          LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
2449
            LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
2451
          LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
2450
            LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
2452
          LEFT JOIN biblio_metadata ON biblio_metadata.biblionumber = biblio.biblionumber
2451
            LEFT JOIN biblio_metadata ON biblio_metadata.biblionumber = biblio.biblionumber
2453
          WHERE items.deleted_at IS NULL
2452
            WHERE items.deleted_at IS NULL
2454
    };
2453
    };
2455
    if (defined $where_str and $where_str ne '') {
2454
    if (defined $where_str and $where_str ne '') {
2456
        $query .= qq{ AND $where_str };
2455
        $query .= qq{ AND $where_str };
2457
- 

Return to bug 20271