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

(-)a/C4/Items.pm (-259 lines)
Lines 34-42 BEGIN { Link Here
34
        ModItemTransfer
34
        ModItemTransfer
35
        CheckItemPreSave
35
        CheckItemPreSave
36
        GetItemsForInventory
36
        GetItemsForInventory
37
        GetItemsInfo
38
        GetItemsLocationInfo
39
        GetHostItemsInfo
40
        get_hostitemnumbers_of
37
        get_hostitemnumbers_of
41
        GetMarcItem
38
        GetMarcItem
42
        CartToShelf
39
        CartToShelf
Lines 669-930 sub GetItemsForInventory { Link Here
669
    return (\@results, $iTotalRecords);
666
    return (\@results, $iTotalRecords);
670
}
667
}
671
668
672
=head2 GetItemsInfo
673
674
  @results = GetItemsInfo($biblionumber);
675
676
Returns information about items with the given biblionumber.
677
678
C<GetItemsInfo> returns a list of references-to-hash. Each element
679
contains a number of keys. Most of them are attributes from the
680
C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
681
Koha database. Other keys include:
682
683
=over 2
684
685
=item C<$data-E<gt>{branchname}>
686
687
The name (not the code) of the branch to which the book belongs.
688
689
=item C<$data-E<gt>{datelastseen}>
690
691
This is simply C<items.datelastseen>, except that while the date is
692
stored in YYYY-MM-DD format in the database, here it is converted to
693
DD/MM/YYYY format. A NULL date is returned as C<//>.
694
695
=item C<$data-E<gt>{datedue}>
696
697
=item C<$data-E<gt>{class}>
698
699
This is the concatenation of C<biblioitems.classification>, the book's
700
Dewey code, and C<biblioitems.subclass>.
701
702
=item C<$data-E<gt>{ocount}>
703
704
I think this is the number of copies of the book available.
705
706
=item C<$data-E<gt>{order}>
707
708
If this is set, it is set to C<One Order>.
709
710
=back
711
712
=cut
713
714
sub GetItemsInfo {
715
    my ( $biblionumber ) = @_;
716
    my $dbh   = C4::Context->dbh;
717
    require C4::Languages;
718
    my $language = C4::Languages::getlanguage();
719
    my $query = "
720
    SELECT items.*,
721
           biblio.*,
722
           biblioitems.volume,
723
           biblioitems.number,
724
           biblioitems.itemtype,
725
           biblioitems.isbn,
726
           biblioitems.issn,
727
           biblioitems.publicationyear,
728
           biblioitems.publishercode,
729
           biblioitems.volumedate,
730
           biblioitems.volumedesc,
731
           biblioitems.lccn,
732
           biblioitems.url,
733
           items.notforloan as itemnotforloan,
734
           issues.borrowernumber,
735
           issues.date_due as datedue,
736
           issues.onsite_checkout,
737
           borrowers.cardnumber,
738
           borrowers.surname,
739
           borrowers.firstname,
740
           borrowers.branchcode as bcode,
741
           serial.serialseq,
742
           serial.publisheddate,
743
           itemtypes.description,
744
           COALESCE( localization.translation, itemtypes.description ) AS translated_description,
745
           itemtypes.notforloan as notforloan_per_itemtype,
746
           holding.branchurl,
747
           holding.branchcode,
748
           holding.branchname,
749
           holding.opac_info as holding_branch_opac_info,
750
           home.opac_info as home_branch_opac_info,
751
           IF(tmp_holdsqueue.itemnumber,1,0) AS has_pending_hold
752
     FROM items
753
     LEFT JOIN branches AS holding ON items.holdingbranch = holding.branchcode
754
     LEFT JOIN branches AS home ON items.homebranch=home.branchcode
755
     LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber
756
     LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
757
     LEFT JOIN issues USING (itemnumber)
758
     LEFT JOIN borrowers USING (borrowernumber)
759
     LEFT JOIN serialitems USING (itemnumber)
760
     LEFT JOIN serial USING (serialid)
761
     LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
762
     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
763
    $query .= q|
764
    LEFT JOIN tmp_holdsqueue USING (itemnumber)
765
    LEFT JOIN localization ON itemtypes.itemtype = localization.code
766
        AND localization.entity = 'itemtypes'
767
        AND localization.lang = ?
768
    |;
769
770
    $query .= " WHERE items.biblionumber = ? ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
771
    my $sth = $dbh->prepare($query);
772
    $sth->execute($language, $biblionumber);
773
    my $i = 0;
774
    my @results;
775
    my $serial;
776
777
    my $userenv = C4::Context->userenv;
778
    my $want_not_same_branch = C4::Context->preference("IndependentBranches") && !C4::Context->IsSuperLibrarian();
779
    while ( my $data = $sth->fetchrow_hashref ) {
780
        if ( $data->{borrowernumber} && $want_not_same_branch) {
781
            $data->{'NOTSAMEBRANCH'} = $data->{'bcode'} ne $userenv->{branch};
782
        }
783
784
        $serial ||= $data->{'serial'};
785
786
        my $descriptions;
787
        # get notforloan complete status if applicable
788
        $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => $data->{frameworkcode}, kohafield => 'items.notforloan', authorised_value => $data->{itemnotforloan} });
789
        $data->{notforloanvalue}     = $descriptions->{lib} // '';
790
        $data->{notforloanvalueopac} = $descriptions->{opac_description} // '';
791
792
        # get restricted status and description if applicable
793
        $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => $data->{frameworkcode}, kohafield => 'items.restricted', authorised_value => $data->{restricted} });
794
        $data->{restrictedvalue}     = $descriptions->{lib} // '';
795
        $data->{restrictedvalueopac} = $descriptions->{opac_description} // '';
796
797
        # my stack procedures
798
        $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => $data->{frameworkcode}, kohafield => 'items.stack', authorised_value => $data->{stack} });
799
        $data->{stack}          = $descriptions->{lib} // '';
800
801
        # Find the last 3 people who borrowed this item.
802
        my $sth2 = $dbh->prepare("SELECT * FROM old_issues,borrowers
803
                                    WHERE itemnumber = ?
804
                                    AND old_issues.borrowernumber = borrowers.borrowernumber
805
                                    ORDER BY returndate DESC
806
                                    LIMIT 3");
807
        $sth2->execute($data->{'itemnumber'});
808
        my $ii = 0;
809
        while (my $data2 = $sth2->fetchrow_hashref()) {
810
            $data->{"timestamp$ii"} = $data2->{'timestamp'} if $data2->{'timestamp'};
811
            $data->{"card$ii"}      = $data2->{'cardnumber'} if $data2->{'cardnumber'};
812
            $data->{"borrower$ii"}  = $data2->{'borrowernumber'} if $data2->{'borrowernumber'};
813
            $ii++;
814
        }
815
816
        $results[$i] = $data;
817
        $i++;
818
    }
819
820
    return $serial
821
        ? sort { ($b->{'publisheddate'} || $b->{'enumchron'} || "") cmp ($a->{'publisheddate'} || $a->{'enumchron'} || "") } @results
822
        : @results;
823
}
824
825
=head2 GetItemsLocationInfo
826
827
  my @itemlocinfo = GetItemsLocationInfo($biblionumber);
828
829
Returns the branch names, shelving location and itemcallnumber for each item attached to the biblio in question
830
831
C<GetItemsInfo> returns a list of references-to-hash. Data returned:
832
833
=over 2
834
835
=item C<$data-E<gt>{homebranch}>
836
837
Branch Name of the item's homebranch
838
839
=item C<$data-E<gt>{holdingbranch}>
840
841
Branch Name of the item's holdingbranch
842
843
=item C<$data-E<gt>{location}>
844
845
Item's shelving location code
846
847
=item C<$data-E<gt>{location_intranet}>
848
849
The intranet description for the Shelving Location as set in authorised_values 'LOC'
850
851
=item C<$data-E<gt>{location_opac}>
852
853
The OPAC description for the Shelving Location as set in authorised_values 'LOC'.  Falls back to intranet description if no OPAC 
854
description is set.
855
856
=item C<$data-E<gt>{itemcallnumber}>
857
858
Item's itemcallnumber
859
860
=item C<$data-E<gt>{cn_sort}>
861
862
Item's call number normalized for sorting
863
864
=back
865
866
=cut
867
868
sub GetItemsLocationInfo {
869
        my $biblionumber = shift;
870
        my @results;
871
872
	my $dbh = C4::Context->dbh;
873
	my $query = "SELECT a.branchname as homebranch, b.branchname as holdingbranch, 
874
			    location, itemcallnumber, cn_sort
875
		     FROM items, branches as a, branches as b
876
		     WHERE homebranch = a.branchcode AND holdingbranch = b.branchcode 
877
		     AND biblionumber = ?
878
		     ORDER BY cn_sort ASC";
879
	my $sth = $dbh->prepare($query);
880
        $sth->execute($biblionumber);
881
882
        while ( my $data = $sth->fetchrow_hashref ) {
883
             my $av = Koha::AuthorisedValues->search({ category => 'LOC', authorised_value => $data->{location} });
884
             $av = $av->count ? $av->next : undef;
885
             $data->{location_intranet} = $av ? $av->lib : '';
886
             $data->{location_opac}     = $av ? $av->opac_description : '';
887
	     push @results, $data;
888
	}
889
	return @results;
890
}
891
892
=head2 GetHostItemsInfo
893
894
    $hostiteminfo = GetHostItemsInfo($hostfield);
895
    Returns the iteminfo for items linked to records via a host field
896
897
=cut
898
899
sub GetHostItemsInfo {
900
    my ($record) = @_;
901
    my @returnitemsInfo;
902
903
    if( !C4::Context->preference('EasyAnalyticalRecords') ) {
904
        return @returnitemsInfo;
905
    }
906
907
    my @fields;
908
    if( C4::Context->preference('marcflavour') eq 'MARC21' ) {
909
        @fields = $record->field('773');
910
    } elsif( C4::Context->preference('marcflavour') eq 'UNIMARC') {
911
        @fields = $record->field('461');
912
    }
913
914
    foreach my $hostfield ( @fields ) {
915
        my $hostbiblionumber = $hostfield->subfield("0");
916
        my $linkeditemnumber = $hostfield->subfield("9");
917
        my @hostitemInfos = GetItemsInfo($hostbiblionumber);
918
        foreach my $hostitemInfo (@hostitemInfos) {
919
            if( $hostitemInfo->{itemnumber} eq $linkeditemnumber ) {
920
                push @returnitemsInfo, $hostitemInfo;
921
                last;
922
            }
923
        }
924
    }
925
    return @returnitemsInfo;
926
}
927
928
=head2 get_hostitemnumbers_of
669
=head2 get_hostitemnumbers_of
929
670
930
  my @itemnumbers_of = get_hostitemnumbers_of($biblionumber);
671
  my @itemnumbers_of = get_hostitemnumbers_of($biblionumber);
(-)a/t/db_dependent/Items.t (-79 / +1 lines)
Lines 19-25 use Modern::Perl; Link Here
19
use Data::Dumper;
19
use Data::Dumper;
20
20
21
use MARC::Record;
21
use MARC::Record;
22
use C4::Items qw( ModItemTransfer GetItemsInfo SearchItems AddItemFromMarc ModItemFromMarc get_hostitemnumbers_of Item2Marc );
22
use C4::Items qw( ModItemTransfer SearchItems AddItemFromMarc ModItemFromMarc get_hostitemnumbers_of Item2Marc );
23
use C4::Biblio qw( GetMarcFromKohaField AddBiblio );
23
use C4::Biblio qw( GetMarcFromKohaField AddBiblio );
24
use C4::Circulation qw( AddIssue );
24
use C4::Circulation qw( AddIssue );
25
use Koha::Items;
25
use Koha::Items;
Lines 190-273 subtest 'ModItemTransfer tests' => sub { Link Here
190
    $schema->storage->txn_rollback;
190
    $schema->storage->txn_rollback;
191
};
191
};
192
192
193
subtest 'GetItemsInfo tests' => sub {
194
195
    plan tests => 9;
196
197
    $schema->storage->txn_begin;
198
199
    my $builder = t::lib::TestBuilder->new;
200
    my $library1 = $builder->build({
201
        source => 'Branch',
202
    });
203
    my $library2 = $builder->build({
204
        source => 'Branch',
205
    });
206
    my $itemtype = $builder->build({
207
        source => 'Itemtype',
208
    });
209
210
    Koha::AuthorisedValues->delete;
211
    my $av1 = Koha::AuthorisedValue->new(
212
        {
213
            category         => 'RESTRICTED',
214
            authorised_value => '1',
215
            lib              => 'Restricted Access',
216
            lib_opac         => 'Restricted Access OPAC',
217
        }
218
    )->store();
219
220
    # Add a biblio
221
    my $biblio = $builder->build_sample_biblio();
222
    # Add an item
223
    my $itemnumber = $builder->build_sample_item(
224
        {
225
            biblionumber  => $biblio->biblionumber,
226
            homebranch    => $library1->{branchcode},
227
            holdingbranch => $library2->{branchcode},
228
            itype         => $itemtype->{itemtype},
229
            restricted    => 1,
230
        }
231
    )->itemnumber;
232
233
    my $library = Koha::Libraries->find( $library1->{branchcode} );
234
    $library->opac_info("homebranch OPAC info");
235
    $library->store;
236
237
    $library = Koha::Libraries->find( $library2->{branchcode} );
238
    $library->opac_info("holdingbranch OPAC info");
239
    $library->store;
240
241
    my @results = GetItemsInfo( $biblio->biblionumber );
242
    ok( @results, 'GetItemsInfo returns results');
243
244
    is( $results[0]->{ home_branch_opac_info }, "homebranch OPAC info",
245
        'GetItemsInfo returns the correct home branch OPAC info notice' );
246
    is( $results[0]->{ holding_branch_opac_info }, "holdingbranch OPAC info",
247
        'GetItemsInfo returns the correct holding branch OPAC info notice' );
248
    is( exists( $results[0]->{ onsite_checkout } ), 1,
249
        'GetItemsInfo returns a onsite_checkout key' );
250
    is( $results[0]->{ restricted }, 1,
251
        'GetItemsInfo returns a restricted value code' );
252
    is( $results[0]->{ restrictedvalue }, "Restricted Access",
253
        'GetItemsInfo returns a restricted value description (staff)' );
254
    is( $results[0]->{ restrictedvalueopac }, "Restricted Access OPAC",
255
        'GetItemsInfo returns a restricted value description (OPAC)' );
256
257
    #place item into holds queue
258
    my $dbh = C4::Context->dbh;
259
    @results = GetItemsInfo( $biblio->biblionumber );
260
    is( $results[0]->{ has_pending_hold }, "0",
261
        'Hold not marked as pending/unavailable if nothing in tmp_holdsqueue for item' );
262
263
    $dbh->do(q{INSERT INTO tmp_holdsqueue (biblionumber, itemnumber, surname, borrowernumber ) VALUES (?, ?, "Zorro", 42)}, undef, $biblio->biblionumber, $itemnumber);
264
    @results = GetItemsInfo( $biblio->biblionumber );
265
    is( $results[0]->{ has_pending_hold }, "1",
266
        'Hold marked as pending/unavailable if tmp_holdsqueue is not empty for item' );
267
268
    $schema->storage->txn_rollback;
269
};
270
271
subtest q{Test Koha::Database->schema()->resultset('Item')->itemtype()} => sub {
193
subtest q{Test Koha::Database->schema()->resultset('Item')->itemtype()} => sub {
272
194
273
    plan tests => 4;
195
    plan tests => 4;
(-)a/t/db_dependent/Items/GetHostItemsInfo.t (-42 lines)
Lines 1-41 Link Here
1
use Modern::Perl;
2
3
use Test::More tests => 1;
4
use t::lib::Mocks;
5
use t::lib::TestBuilder;
6
7
use C4::Items qw( GetHostItemsInfo );
8
use Koha::Database;
9
10
my $schema = Koha::Database->new->schema;
11
$schema->storage->txn_begin;
12
13
subtest 'GetHostItemsInfo' => sub {
14
    plan tests => 3;
15
16
    my $builder = t::lib::TestBuilder->new;
17
    my $bib1 = $builder->build_sample_biblio;
18
    my $itm1 = $builder->build_sample_item({ biblionumber => $bib1->biblionumber });
19
    my $itm2 = $builder->build_sample_item({ biblionumber => $bib1->biblionumber });
20
    my $marc = MARC::Record->new;
21
    $marc->append_fields(
22
        MARC::Field->new( '461', '', '', 0 => $bib1->biblionumber, 9 => $itm1->itemnumber ),
23
        MARC::Field->new( '773', '', '', 0 => $bib1->biblionumber, 9 => $itm1->itemnumber ),
24
        MARC::Field->new( '773', '', '', 0 => $bib1->biblionumber, 9 => $itm2->itemnumber ),
25
    );
26
27
    t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
28
    t::lib::Mocks::mock_preference('EasyAnalyticalRecords', 0);
29
    my @a = C4::Items::GetHostItemsInfo( $marc );
30
    is( @a, 0, 'GetHostItemsInfo returns empty list when pref is disabled' );
31
32
    t::lib::Mocks::mock_preference('EasyAnalyticalRecords', 1);
33
    @a = C4::Items::GetHostItemsInfo( $marc );
34
    is( @a, 2, 'GetHostItemsInfo returns two items for MARC21' );
35
36
    t::lib::Mocks::mock_preference('marcflavour', 'UNIMARC');
37
    @a = C4::Items::GetHostItemsInfo( $marc );
38
    is( @a, 1, 'GetHostItemsInfo returns one item for UNIMARC' );
39
};
40
41
$schema->storage->txn_rollback;
42
- 

Return to bug 27272