]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/biblio.pm
adding OU visiblity restriction to copy count call
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Publisher / biblio.pm
1 package OpenILS::Application::Storage::Publisher::biblio;
2 use base qw/OpenILS::Application::Storage/;
3 use vars qw/$VERSION/;
4 use OpenSRF::EX qw/:try/;
5 #use OpenILS::Application::Storage::CDBI::biblio;
6 #use OpenILS::Application::Storage::CDBI::asset;
7 use OpenILS::Utils::Fieldmapper;
8
9 $VERSION = 1;
10
11 sub record_copy_count {
12         my $self = shift;
13         my $client = shift;
14
15         my %args = @_;
16
17         my $cn_table = asset::call_number->table;
18         my $cp_table = asset::copy->table;
19         my $st_table = config::copy_status->table;
20         my $src_table = config::bib_source->table;
21         my $br_table = biblio::record_entry->table;
22         my $loc_table = asset::copy_location->table;
23         my $out_table = actor::org_unit_type->table;
24
25         my $descendants = "actor.org_unit_descendants(u.id)";
26         my $ancestors = "actor.org_unit_ancestors(?)";
27
28         my $visible = 'AND a.opac_visible = TRUE AND st.holdable = TRUE AND loc.opac_visible = TRUE AND cp.opac_visible = TRUE';
29         if ($self->api_name =~ /staff/o) {
30                 $visible = ''
31         }
32
33         my $sql = <<"   SQL";
34                 SELECT  t.depth,
35                         u.id AS org_unit,
36                         sum(
37                                 (SELECT count(cp.id)
38                                   FROM  $cn_table cn
39                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
40                                         JOIN $descendants a ON (cp.circ_lib = a.id)
41                                         JOIN $st_table st ON (cp.status = st.id)
42                                         JOIN $loc_table loc ON (cp.location = loc.id)
43                                   WHERE cn.record = ?
44                                         $visible
45                                         AND cn.deleted IS FALSE
46                                         AND cp.deleted IS FALSE)
47                         ) AS count,
48                         sum(
49                                 (SELECT count(cp.id)
50                                   FROM  $cn_table cn
51                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
52                                         JOIN $descendants a ON (cp.circ_lib = a.id)
53                                         JOIN $st_table st ON (cp.status = st.id)
54                                         JOIN $loc_table loc ON (cp.location = loc.id)
55                                   WHERE cn.record = ?
56                                         $visible
57                                         AND cn.deleted IS FALSE
58                                         AND cp.deleted IS FALSE
59                                         AND cp.status IN (0,7))
60                         ) AS available,
61                         sum(
62                                 (SELECT count(cp.id)
63                                   FROM  $cn_table cn
64                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
65                                         JOIN $st_table st ON (cp.status = st.id)
66                                         JOIN $loc_table loc ON (cp.location = loc.id)
67                                   WHERE cn.record = ?
68                                         AND st.holdable = TRUE
69                                         AND loc.opac_visible = TRUE
70                                         AND cp.opac_visible = TRUE
71                                         AND cn.deleted IS FALSE
72                                         AND cp.deleted IS FALSE)
73                         ) AS unshadow,
74                         sum(    
75                                 (SELECT sum(1)
76                                   FROM  $br_table br
77                                         JOIN $src_table src ON (src.id = br.source)
78                                   WHERE br.id = ?
79                                         AND src.transcendant IS TRUE
80                                 )
81                         ) AS transcendant
82                   FROM  $ancestors u
83                         JOIN $out_table t ON (u.ou_type = t.id)
84                   GROUP BY 1,2
85         SQL
86
87         my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
88         $sth->execute(''.$args{record}, ''.$args{record}, ''.$args{record}, ''.$args{record}, ''.$args{org_unit});
89         while ( my $row = $sth->fetchrow_hashref ) {
90                 $client->respond( $row );
91         }
92         return undef;
93 }
94 __PACKAGE__->register_method(
95         api_name        => 'open-ils.storage.biblio.record_entry.copy_count',
96         method          => 'record_copy_count',
97         api_level       => 1,
98         stream          => 1,
99         cachable        => 1,
100 );
101 __PACKAGE__->register_method(
102         api_name        => 'open-ils.storage.biblio.record_entry.copy_count.staff',
103         method          => 'record_copy_count',
104         api_level       => 1,
105         stream          => 1,
106         cachable        => 1,
107 );
108
109 sub record_ranged_tree {
110         my $self = shift;
111         my $client = shift;
112         my $r = shift;
113         my $ou = shift;
114         my $depth = shift;
115         my $limit = shift || 0;
116         my $offset = shift || 0;
117
118         my $ou_sql = defined($depth) ?
119                         "SELECT id FROM actor.org_unit_descendants(?,?)":
120                         "SELECT id FROM actor.org_unit_descendants(?)";
121
122         my $ou_list =
123                 actor::org_unit
124                         ->db_Main
125                         ->selectcol_arrayref(
126                                 $ou_sql,
127                                 {},
128                                 $ou,
129                                 (defined($depth) ? ($depth) : ()),
130                         );
131
132         return undef unless ($ou_list and @$ou_list);
133
134         $r = biblio::record_entry->retrieve( $r );
135         return undef unless ($r);
136
137         my $rec = $r->to_fieldmapper;
138         $rec->call_numbers([]);
139
140         $rec->fixed_fields( $r->record_descriptor->next->to_fieldmapper );
141
142         my $offset_count = 0;
143         my $limit_count = 0;
144         for my $cn ( $r->call_numbers  ) {
145                 next if ($cn->deleted);
146                 my $call_number = $cn->to_fieldmapper;
147                 $call_number->copies([]);
148
149
150                 for my $cp ( $cn->copies(circ_lib => $ou_list) ) {
151                         next if ($cp->deleted);
152                         if ($offset > 0 && $offset_count < $offset) {
153                                 $offset_count++;
154                                 next;
155                         }
156                         
157                         last if ($limit > 0 && $limit_count >= $limit);
158
159                         my $copy = $cp->to_fieldmapper;
160                         $copy->status( $cp->status->to_fieldmapper );
161                         $copy->location( $cp->location->to_fieldmapper );
162                         push @{ $call_number->copies }, $copy;
163
164                         $limit_count++;
165                 }
166
167                 last if ($limit > 0 && $limit_count >= $limit);
168
169                 push @{ $rec->call_numbers }, $call_number if (@{ $call_number->copies });
170         }
171
172         return $rec;
173 }
174 __PACKAGE__->register_method(
175         api_name        => 'open-ils.storage.biblio.record_entry.ranged_tree',
176         method          => 'record_ranged_tree',
177         argc            => 1,
178         api_level       => 1,
179 );
180
181 sub record_by_barcode {
182         my $self = shift;
183         my $client = shift;
184
185         my $cn_table = asset::call_number->table;
186         my $cp_table = asset::copy->table;
187
188         my $id = ''.shift;
189         my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"   SQL", {}, $id );
190                 SELECT  cn.record
191                   FROM  $cn_table cn
192                         JOIN $cp_table cp ON (cp.call_number = cn.id)
193                   WHERE cp.barcode = ?
194         SQL
195
196         my $rec = biblio::record_entry->retrieve( $r );
197
198         return $rec->to_fieldmapper if ($rec);
199         return undef;
200 }
201 __PACKAGE__->register_method(
202         api_name        => 'open-ils.storage.biblio.record_entry.retrieve_by_barcode',
203         method          => 'record_by_barcode',
204         api_level       => 1,
205         cachable        => 1,
206 );
207
208 sub record_by_copy {
209         my $self = shift;
210         my $client = shift;
211
212         my $cn_table = asset::call_number->table;
213         my $cp_table = asset::copy->table;
214
215         my $id = ''.shift;
216         my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"   SQL", {}, $id );
217                 SELECT  cn.record
218                   FROM  $cn_table cn
219                         JOIN $cp_table cp ON (cp.call_number = cn.id)
220                   WHERE cp.id = ?
221         SQL
222
223         my $rec = biblio::record_entry->retrieve( $r );
224         return undef unless ($rec);
225
226         my $r_fm = $rec->to_fieldmapper;
227         my $ff = $rec->record_descriptor->next;
228         $r_fm->fixed_fields( $ff->to_fieldmapper ) if ($ff);
229
230         return $r_fm;
231 }
232 __PACKAGE__->register_method(
233         api_name        => 'open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy',
234         method          => 'record_by_copy',
235         api_level       => 1,
236         cachable        => 1,
237 );
238
239
240 =comment Old version
241
242 my $org_unit_lookup;
243 sub record_copy_count {
244         my $self = shift;
245         my $client = shift;
246         my $oid = shift;
247         my @recs = @_;
248
249         if ($self->api_name !~ /batch/o) {
250                 @recs = ($recs[0]);
251         }
252
253         throw OpenSRF::EX::InvalidArg ( "No org_unit id passed!" )
254                 unless ($oid);
255
256         throw OpenSRF::EX::InvalidArg ( "No record id passed!" )
257                 unless (@recs);
258
259         $org_unit_lookup ||= $self->method_lookup('open-ils.storage.direct.actor.org_unit.retrieve');
260         my ($org_unit) = $org_unit_lookup->run($oid);
261
262         # XXX Use descendancy tree here!!!
263         my $short_name_hack = $org_unit->shortname;
264         $short_name_hack = '' if (!$org_unit->parent_ou);
265         $short_name_hack .= '%';
266         # XXX Use descendancy tree here!!!
267
268         my $rec_list = join(',',@recs);
269
270         my $cp_table = asset::copy->table;
271         my $cn_table = asset::call_number->table;
272
273         my $select =<<" SQL";
274                 SELECT  count(cp.*) as copies
275                   FROM  $cn_table cn
276                         JOIN $cp_table cp ON (cp.call_number = cn.id)
277                   WHERE cn.owning_lib LIKE ? AND
278                         cn.record IN ($rec_list)
279         SQL
280
281         my $sth = asset::copy->db_Main->prepare_cached($select);
282         $sth->execute($short_name_hack);
283
284         my $results = $sth->fetchall_hashref('record');
285
286         $client->respond($$results{$_}{copies} || 0) for (@recs);
287
288         return undef;
289 }
290 __PACKAGE__->register_method(
291         method          => 'record_copy_count',
292         api_name        => 'open-ils.storage.direct.biblio.record_copy_count',
293         api_level       => 1,
294         argc            => 1,
295 );
296 __PACKAGE__->register_method(
297         method          => 'record_copy_count',
298         api_name        => 'open-ils.storage.direct.biblio.record_copy_count.batch',
299         api_level       => 1,
300         argc            => 1,
301         stream          => 1,
302 );
303
304 =cut
305
306 sub global_record_copy_count {
307         my $self = shift;
308         my $client = shift;
309
310         my $rec = shift;
311
312         my $cn_table = asset::call_number->table;
313         my $cp_table = asset::copy->table;
314         my $cl_table = asset::copy_location->table;
315         my $cs_table = config::copy_status->table;
316
317         my $copies_visible = 'AND cp.opac_visible IS TRUE AND cs.holdable IS TRUE AND cl.opac_visible IS TRUE';
318         $copies_visible = '' if ($self->api_name =~ /staff/o);
319
320         my $sql = <<"   SQL";
321
322                 SELECT  owning_lib, sum(avail), sum(tot)
323                   FROM  (
324                                 SELECT  cn.owning_lib, count(cp.id) as avail, 0 as tot
325                                   FROM  $cn_table cn
326                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
327                                         JOIN $cs_table cs ON (cs.id = cp.status)
328                                         JOIN $cl_table cl ON (cl.id = cp.location)
329                                   WHERE cn.record = ?
330                                         AND cp.status IN (0,7)
331                                         $copies_visible
332                                   GROUP BY 1
333                                                 UNION
334                                 SELECT  cn.owning_lib, 0 as avail, count(cp.id) as tot
335                                   FROM  $cn_table cn
336                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
337                                         JOIN $cs_table cs ON (cs.id = cp.status)
338                                         JOIN $cl_table cl ON (cl.id = cp.location)
339                                   WHERE cn.record = ?
340                                         $copies_visible
341                                   GROUP BY 1
342                         ) x
343                   GROUP BY 1
344         SQL
345
346         my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
347         $sth->execute("$rec", "$rec");
348
349         $client->respond( $_ ) for (@{$sth->fetchall_arrayref});
350         return undef;
351 }
352 __PACKAGE__->register_method(
353         api_name        => 'open-ils.storage.biblio.record_entry.global_copy_count',
354         method          => 'global_record_copy_count',
355         api_level       => 1,
356         stream          => 1,
357         cachable        => 1,
358 );
359 __PACKAGE__->register_method(
360         api_name        => 'open-ils.storage.biblio.record_entry.global_copy_count.staff',
361         method          => 'global_record_copy_count',
362         api_level       => 1,
363         stream          => 1,
364         cachable        => 1,
365 );
366
367 sub record_copy_status_count {
368         my $self = shift;
369         my $client = shift;
370
371         my $rec = shift;
372         my $ou = shift || 1;
373         my $depth = shift || 0;
374
375
376         my $descendants = "actor.org_unit_descendants(?,?)";
377
378         my $cn_table = asset::call_number->table;
379         my $cp_table = asset::copy->table;
380         my $cl_table = asset::copy_location->table;
381         my $cs_table = config::copy_status->table;
382
383         my $sql = <<"   SQL";
384
385                 SELECT  cp.circ_lib, cn.label, cp.status, count(cp.id)
386                   FROM  $cp_table cp,
387                         $cn_table cn,
388                         $cl_table cl,
389                         $cs_table cs,
390                         $descendants d
391                   WHERE cn.record = ?
392                         AND cp.call_number = cn.id
393                         AND cp.location = cl.id
394                         AND cp.circ_lib = d.id
395                         AND cp.status = cs.id
396                         AND cl.opac_visible IS TRUE
397                         AND cp.opac_visible IS TRUE
398                         AND cp.deleted IS FALSE
399                         AND cs.holdable
400                   GROUP BY 1,2,3;
401         SQL
402
403         my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
404         $sth->execute($ou, $depth, "$rec" );
405
406         my %data = ();
407         for my $row (@{$sth->fetchall_arrayref}) {
408                 $data{$$row[0]}{$$row[1]}{$$row[2]} += $$row[3];
409         }
410         
411         for my $ou (keys %data) {
412                 for my $cn (keys %{$data{$ou}}) {
413                         $client->respond( [$ou, $cn, $data{$ou}{$cn}] );
414                 }
415         }
416         return undef;
417 }
418 __PACKAGE__->register_method(
419         api_name        => 'open-ils.storage.biblio.record_entry.status_copy_count',
420         method          => 'record_copy_status_count',
421         api_level       => 1,
422         stream          => 1,
423         cachable        => 1,
424 );
425
426 1;