followup - make barcode_to_borrowernumber() work as named
[koha_fer] / C4 / SIP / ILS / Item.pm
1 #
2 # ILS::Item.pm
3
4 # A Class for hiding the ILS's concept of the item from the OpenSIP
5 # system
6 #
7
8 package ILS::Item;
9
10 use strict;
11 use warnings;
12
13 use Sys::Syslog qw(syslog);
14
15 use ILS::Transaction;
16
17 use C4::Debug;
18 use C4::Context;
19 use C4::Biblio;
20 use C4::Items;
21 use C4::Circulation;
22 use C4::Members;
23 use C4::Reserves;
24
25 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
26
27 BEGIN {
28         $VERSION = 2.10;
29         require Exporter;
30         @ISA = qw(Exporter);
31         @EXPORT_OK = qw();
32 }
33
34 =head2 EXAMPLE
35
36 our %item_db = (
37     '1565921879' => {
38         title => "Perl 5 desktop reference",
39         id => '1565921879',
40         sip_media_type => '001',
41         magnetic_media => 0,
42         hold_queue => [],
43     },
44     '0440242746' => {
45         title => "The deep blue alibi",
46         id => '0440242746',
47         sip_media_type => '001',
48         magnetic_media => 0,
49         hold_queue => [
50             {
51             itemnumber => '823',
52             priority => '1',
53             reservenotes => undef,
54             constrainttype => 'a',
55             reservedate => '2008-10-09',
56             found => undef,
57             rtimestamp => '2008-10-09 11:15:06',
58             biblionumber => '406',
59             borrowernumber => '756',
60             branchcode => 'CPL'
61             }
62         ],
63     },
64     '660' => {
65         title => "Harry Potter y el cáliz de fuego",
66         id => '660',
67         sip_media_type => '001',
68         magnetic_media => 0,
69         hold_queue => [],
70     },
71 );
72 =cut
73
74 sub priority_sort {
75     defined $a->{priority} or return -1;
76     defined $b->{priority} or return 1;
77     return $a->{priority} <=> $b->{priority};
78 }
79
80 sub new {
81         my ($class, $item_id) = @_;
82         my $type = ref($class) || $class;
83         my $self;
84         my $item = GetBiblioFromItemNumber( GetItemnumberFromBarcode($item_id) );
85         
86         if (! $item) {
87                 syslog("LOG_DEBUG", "new ILS::Item('%s'): not found", $item_id);
88                 warn "new ILS::Item($item_id) : No item '$item_id'.";
89                 return undef;
90         }
91     $item->{'id'} = $item->{'barcode'};
92         # check if its on issue and if so get the borrower
93         my $issue = GetItemIssue($item->{'itemnumber'});
94         my $borrower = GetMember($issue->{'borrowernumber'},'borrowernumber');
95         $item->{patron} = $borrower->{'cardnumber'};
96         my @reserves = (@{ GetReservesFromBiblionumber($item->{biblionumber}) });
97         $item->{hold_queue} = [ sort priority_sort @reserves ];
98         # $item->{joetest} = 111;
99         $self = $item;
100         bless $self, $type;
101
102     syslog("LOG_DEBUG", "new ILS::Item('%s'): found with title '%s'",
103            $item_id, $self->{title});
104
105     return $self;
106 }
107
108 sub magnetic {
109     my $self = shift;
110     return $self->{magnetic_media};
111 }
112 sub sip_media_type {
113     my $self = shift;
114     return $self->{sip_media_type};
115 }
116 sub sip_item_properties {
117     my $self = shift;
118     return $self->{sip_item_properties};
119 }
120
121 sub status_update {     # FIXME: this looks unimplemented
122     my ($self, $props) = @_;
123     my $status = new ILS::Transaction;
124     $self->{sip_item_properties} = $props;
125     $status->{ok} = 1;
126     return $status;
127 }
128     
129 sub id {
130     my $self = shift;
131     return $self->{id};
132 }
133 sub title_id {
134     my $self = shift;
135     return $self->{title};
136 }
137 sub permanent_location {
138     my $self = shift;
139     return $self->{permanent_location} || '';
140 }
141 sub current_location {
142     my $self = shift;
143     return $self->{current_location} || '';
144 }
145
146 sub sip_circulation_status {
147     my $self = shift;
148     if ($self->{patron}) {
149                 return '04';    # charged
150     } elsif (scalar @{$self->{hold_queue}}) {
151                 return '08';    # waiting on hold shelf
152     } else {
153                 return '03';    # available
154     }                   # FIXME: 01-13 enumerated in spec.
155 }
156
157 sub sip_security_marker {
158     return '02';        # FIXME? 00-other; 01-None; 02-Tattle-Tape Security Strip (3M); 03-Whisper Tape (3M)
159 }
160 sub sip_fee_type {
161     return '01';    # FIXME? 01-09 enumerated in spec.  We just use O1-other/unknown.
162 }
163
164 sub fee {
165     my $self = shift;
166     return $self->{fee} || 0;
167 }
168 sub fee_currency {
169     my $self = shift;
170     return $self->{currency} || 'USD';
171 }
172 sub owner {
173     my $self = shift;
174     return 'CPL';       # FIXME: UWOLS was hardcoded 
175 }
176 sub hold_queue {
177     my $self = shift;
178         (defined $self->{hold_queue}) or return [];
179     return $self->{hold_queue};
180 }
181
182 sub hold_queue_position {
183         my ($self, $patron_id) = @_;
184         ($self->{hold_queue}) or return 0;
185         my $i = 0;
186         foreach (@{$self->{hold_queue}}) {
187                 $i++;
188                 $_->{patron_id} or next;
189                 if ($self->barcode_is_borrowernumber($patron_id, $_->{borrowernumber})) {
190                         return $i;  # maybe should return $_->{priority}
191                 }
192         }
193     return 0;
194 }
195
196 sub due_date {
197     my $self = shift;
198     return $self->{due_date} || 0;
199 }
200 sub recall_date {
201     my $self = shift;
202     return $self->{recall_date} || 0;
203 }
204 sub hold_pickup_date {
205     my $self = shift;
206     return $self->{hold_pickup_date} || 0;
207 }
208 sub screen_msg {
209     my $self = shift;
210     return $self->{screen_msg} || '';
211 }
212 sub print_line {
213         my $self = shift;
214         return $self->{print_line} || '';
215 }
216
217 # This is a partial check of "availability".  It is not supposed to check everything here.
218 # An item is available for a patron if it is:
219 # 1) checked out to the same patron and there's no hold queue
220 # OR
221 # 2) not checked out and (there's no hold queue OR patron
222 #    is at the front of the queue)
223 sub available {
224         my ($self, $for_patron) = @_;
225         my $count = (defined $self->{hold_queue}) ? scalar @{$self->{hold_queue}} : 0;
226         $debug and print STDERR "availability check: hold_queue size $count\n";
227     if (defined($self->{patron_id})) {
228                 ($self->{patron_id} eq $for_patron) or return 0;
229                 return ($count ? 0 : 1);
230         } else {        # not checked out
231                 ($count) or return 1;
232                 ($self->barcode_is_borrowernumber($for_patron, $self->{hold_queue}[0]->{borrowernumber})) and return 1;
233         }
234         return 0;
235 }
236
237 sub barcode_to_borrowernumber ($) {
238     my $known = shift;
239     (defined($known)) or return undef;
240     my $member = GetMember($known, 'cardnumber') or return undef; # borrowernumber is default type for GetMember lookup
241     return $member->{borrowernumber};
242 }
243 sub barcode_is_borrowernumber ($$$) {    # because hold_queue only has borrowernumber...
244     my $self = shift;   # not really used
245     my $barcode = shift;
246     my $number  = shift or return undef;    # can't be zero
247     (defined($barcode)) or return undef;    # might be 0 or 000 or 000000
248     my $converted = barcode_to_borrowernumber($barcode) or return undef;
249     return ($number eq $converted); # even though both *should* be numbers, eq is safer.
250 }
251 1;
252 __END__
253