]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/biblio.pm
Post-2.5-m1 whitespace fixup
[Evergreen.git] / Open-ILS / src / perlmods / lib / 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(?) u JOIN $out_table t ON (u.ou_type = t.id)";
27
28     if ($args{org_unit} < 0) {
29         $args{org_unit} *= -1;
30         $ancestors = "(select org_unit as id from actor.org_lasso_map where lasso = ?) u CROSS JOIN (SELECT -1 AS depth) t";
31     }
32
33     my $visible = 'AND a.opac_visible = TRUE AND st.opac_visible = TRUE AND loc.opac_visible = TRUE AND cp.opac_visible = TRUE';
34     if ($self->api_name =~ /staff/o) {
35         $visible = ''
36     }
37
38     my $sql = <<"    SQL";
39         SELECT  t.depth,
40             u.id AS org_unit,
41             sum(
42                 (SELECT count(cp.id)
43                   FROM  $cn_table cn
44                     JOIN $cp_table cp ON (cn.id = cp.call_number)
45                     JOIN $descendants a ON (cp.circ_lib = a.id)
46                     JOIN $st_table st ON (cp.status = st.id)
47                     JOIN $loc_table loc ON (cp.location = loc.id)
48                   WHERE cn.record = ?
49                     $visible
50                     AND cn.deleted IS FALSE
51                     AND cp.deleted IS FALSE)
52             ) AS count,
53             sum(
54                 (SELECT count(cp.id)
55                   FROM  $cn_table cn
56                     JOIN $cp_table cp ON (cn.id = cp.call_number)
57                     JOIN $descendants a ON (cp.circ_lib = a.id)
58                     JOIN $st_table st ON (cp.status = st.id)
59                     JOIN $loc_table loc ON (cp.location = loc.id)
60                   WHERE cn.record = ?
61                     $visible
62                     AND cn.deleted IS FALSE
63                     AND cp.deleted IS FALSE
64                     AND cp.status IN (0,7,12))
65             ) AS available,
66             sum(
67                 (SELECT count(cp.id)
68                   FROM  $cn_table cn
69                     JOIN $cp_table cp ON (cn.id = cp.call_number)
70                     JOIN $st_table st ON (cp.status = st.id)
71                     JOIN $loc_table loc ON (cp.location = loc.id)
72                   WHERE cn.record = ?
73                     AND st.opac_visible = TRUE
74                     AND loc.opac_visible = TRUE
75                     AND cp.opac_visible = TRUE
76                     AND cn.deleted IS FALSE
77                     AND cp.deleted IS FALSE)
78             ) AS unshadow,
79                         sum(    
80                                 (SELECT sum(1)
81                                   FROM  $br_table br
82                                         JOIN $src_table src ON (src.id = br.source)
83                                   WHERE br.id = ?
84                                         AND src.transcendant IS TRUE
85                                 )
86                         ) AS transcendant
87           FROM  $ancestors
88           GROUP BY 1,2
89     SQL
90
91     my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
92     $sth->execute(''.$args{record}, ''.$args{record}, ''.$args{record}, ''.$args{record}, ''.$args{org_unit});
93     while ( my $row = $sth->fetchrow_hashref ) {
94         $client->respond( $row );
95     }
96     return undef;
97 }
98 __PACKAGE__->register_method(
99     api_name    => 'open-ils.storage.biblio.record_entry.copy_count',
100     method      => 'record_copy_count',
101     api_level   => 1,
102     stream      => 1,
103     cachable    => 1,
104 );
105 __PACKAGE__->register_method(
106     api_name    => 'open-ils.storage.biblio.record_entry.copy_count.staff',
107     method      => 'record_copy_count',
108     api_level   => 1,
109     stream      => 1,
110     cachable    => 1,
111 );
112
113 sub record_ranged_tree {
114     my $self = shift;
115     my $client = shift;
116     my $r = shift;
117     my $ou = shift;
118     my $depth = shift;
119     my $limit = shift || 0;
120     my $offset = shift || 0;
121
122     my $ou_sql = defined($depth) ?
123             "SELECT id FROM actor.org_unit_descendants(?,?)":
124             "SELECT id FROM actor.org_unit_descendants(?)";
125
126     my $ou_list =
127         actor::org_unit
128             ->db_Main
129             ->selectcol_arrayref(
130                 $ou_sql,
131                 {},
132                 $ou,
133                 (defined($depth) ? ($depth) : ()),
134             );
135
136     return undef unless ($ou_list and @$ou_list);
137
138     $r = biblio::record_entry->retrieve( $r );
139     return undef unless ($r);
140
141     my $rec = $r->to_fieldmapper;
142     $rec->call_numbers([]);
143
144     $rec->fixed_fields( $r->record_descriptor->next->to_fieldmapper );
145
146     my $offset_count = 0;
147     my $limit_count = 0;
148     for my $cn ( $r->call_numbers  ) {
149         next if ($cn->deleted);
150         my $call_number = $cn->to_fieldmapper;
151         $call_number->copies([]);
152
153
154         for my $cp ( $cn->copies(circ_lib => $ou_list) ) {
155             next if ($cp->deleted);
156             if ($offset > 0 && $offset_count < $offset) {
157                 $offset_count++;
158                 next;
159             }
160             
161             last if ($limit > 0 && $limit_count >= $limit);
162
163             my $copy = $cp->to_fieldmapper;
164             $copy->status( $cp->status->to_fieldmapper );
165             $copy->location( $cp->location->to_fieldmapper );
166             push @{ $call_number->copies }, $copy;
167
168             $limit_count++;
169         }
170
171         last if ($limit > 0 && $limit_count >= $limit);
172
173         push @{ $rec->call_numbers }, $call_number if (@{ $call_number->copies });
174     }
175
176     return $rec;
177 }
178 __PACKAGE__->register_method(
179     api_name    => 'open-ils.storage.biblio.record_entry.ranged_tree',
180     method      => 'record_ranged_tree',
181     argc        => 1,
182     api_level   => 1,
183 );
184
185 sub record_by_barcode {
186     my $self = shift;
187     my $client = shift;
188
189     my $cn_table = asset::call_number->table;
190     my $cp_table = asset::copy->table;
191
192     my $id = ''.shift;
193     my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"    SQL", {}, $id );
194         SELECT  cn.record
195           FROM  $cn_table cn
196             JOIN $cp_table cp ON (cp.call_number = cn.id)
197           WHERE cp.barcode = ?
198     SQL
199
200     my $rec = biblio::record_entry->retrieve( $r );
201
202     return $rec->to_fieldmapper if ($rec);
203     return undef;
204 }
205 __PACKAGE__->register_method(
206     api_name    => 'open-ils.storage.biblio.record_entry.retrieve_by_barcode',
207     method      => 'record_by_barcode',
208     api_level   => 1,
209     cachable    => 1,
210 );
211
212 sub record_by_copy {
213     my $self = shift;
214     my $client = shift;
215
216     my $cn_table = asset::call_number->table;
217     my $cp_table = asset::copy->table;
218
219     my $id = ''.shift;
220     my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"    SQL", {}, $id );
221         SELECT  cn.record
222           FROM  $cn_table cn
223             JOIN $cp_table cp ON (cp.call_number = cn.id)
224           WHERE cp.id = ?
225     SQL
226
227     my $rec = biblio::record_entry->retrieve( $r );
228     return undef unless ($rec);
229
230     my $r_fm = $rec->to_fieldmapper;
231     my $ff = $rec->record_descriptor->next;
232     $r_fm->fixed_fields( $ff->to_fieldmapper ) if ($ff);
233
234     return $r_fm;
235 }
236 __PACKAGE__->register_method(
237     api_name    => 'open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy',
238     method      => 'record_by_copy',
239     api_level   => 1,
240     cachable    => 1,
241 );
242
243
244 =head1 comment Old version
245
246 my $org_unit_lookup;
247 sub record_copy_count {
248     my $self = shift;
249     my $client = shift;
250     my $oid = shift;
251     my @recs = @_;
252
253     if ($self->api_name !~ /batch/o) {
254         @recs = ($recs[0]);
255     }
256
257     throw OpenSRF::EX::InvalidArg ( "No org_unit id passed!" )
258         unless ($oid);
259
260     throw OpenSRF::EX::InvalidArg ( "No record id passed!" )
261         unless (@recs);
262
263     $org_unit_lookup ||= $self->method_lookup('open-ils.storage.direct.actor.org_unit.retrieve');
264     my ($org_unit) = $org_unit_lookup->run($oid);
265
266     # XXX Use descendancy tree here!!!
267     my $short_name_hack = $org_unit->shortname;
268     $short_name_hack = '' if (!$org_unit->parent_ou);
269     $short_name_hack .= '%';
270     # XXX Use descendancy tree here!!!
271
272     my $rec_list = join(',',@recs);
273
274     my $cp_table = asset::copy->table;
275     my $cn_table = asset::call_number->table;
276
277     my $select =<<"    SQL";
278         SELECT  count(cp.*) as copies
279           FROM  $cn_table cn
280             JOIN $cp_table cp ON (cp.call_number = cn.id)
281           WHERE cn.owning_lib LIKE ? AND
282             cn.record IN ($rec_list)
283     SQL
284
285     my $sth = asset::copy->db_Main->prepare_cached($select);
286     $sth->execute($short_name_hack);
287
288     my $results = $sth->fetchall_hashref('record');
289
290     $client->respond($$results{$_}{copies} || 0) for (@recs);
291
292     return undef;
293 }
294 __PACKAGE__->register_method(
295     method      => 'record_copy_count',
296     api_name    => 'open-ils.storage.direct.biblio.record_copy_count',
297     api_level   => 1,
298     argc        => 1,
299 );
300 __PACKAGE__->register_method(
301     method      => 'record_copy_count',
302     api_name    => 'open-ils.storage.direct.biblio.record_copy_count.batch',
303     api_level   => 1,
304     argc        => 1,
305     stream      => 1,
306 );
307
308 =cut
309
310 sub global_record_copy_count {
311     my $self = shift;
312     my $client = shift;
313
314     my $rec = shift;
315
316     my $cn_table = asset::call_number->table;
317     my $cp_table = asset::copy->table;
318     my $cl_table = asset::copy_location->table;
319     my $cs_table = config::copy_status->table;
320
321     my $copies_visible = 'AND cp.opac_visible IS TRUE AND cs.opac_visible IS TRUE AND cl.opac_visible IS TRUE';
322     $copies_visible = '' if ($self->api_name =~ /staff/o);
323
324     my $sql = <<"    SQL";
325
326         SELECT  owning_lib, sum(avail), sum(tot)
327           FROM  (
328                     SELECT  cn.owning_lib, count(cp.id) as avail, 0 as tot
329                   FROM  $cn_table cn
330                     JOIN $cp_table cp ON (cn.id = cp.call_number)
331                     JOIN $cs_table cs ON (cs.id = cp.status)
332                     JOIN $cl_table cl ON (cl.id = cp.location)
333                   WHERE cn.record = ?
334                     AND cp.status IN (0,7,12)
335                     $copies_visible
336                   GROUP BY 1
337                                     UNION
338                     SELECT  cn.owning_lib, 0 as avail, count(cp.id) as tot
339                   FROM  $cn_table cn
340                     JOIN $cp_table cp ON (cn.id = cp.call_number)
341                     JOIN $cs_table cs ON (cs.id = cp.status)
342                     JOIN $cl_table cl ON (cl.id = cp.location)
343                   WHERE cn.record = ?
344                     $copies_visible
345                   GROUP BY 1
346             ) x
347           GROUP BY 1
348     SQL
349
350     my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
351     $sth->execute("$rec", "$rec");
352
353     $client->respond( $_ ) for (@{$sth->fetchall_arrayref});
354     return undef;
355 }
356 __PACKAGE__->register_method(
357     api_name    => 'open-ils.storage.biblio.record_entry.global_copy_count',
358     method      => 'global_record_copy_count',
359     api_level   => 1,
360     stream      => 1,
361     cachable    => 1,
362 );
363 __PACKAGE__->register_method(
364     api_name    => 'open-ils.storage.biblio.record_entry.global_copy_count.staff',
365     method      => 'global_record_copy_count',
366     api_level   => 1,
367     stream      => 1,
368     cachable    => 1,
369 );
370
371 sub record_copy_status_count {
372     my $self = shift;
373     my $client = shift;
374
375     my $rec = shift;
376     my $ou = shift || 1;
377     my $depth = shift || 0;
378
379
380     my $descendants = "actor.org_unit_descendants(?,?)";
381
382     my $cn_table = asset::call_number->table;
383     my $cnp_table = asset::call_number_prefix->table;
384     my $cns_table = asset::call_number_suffix->table;
385     my $cp_table = asset::copy->table;
386     my $cl_table = asset::copy_location->table;
387     my $cs_table = config::copy_status->table;
388
389     my $sql = <<"    SQL";
390
391         SELECT  cp.circ_lib,
392                 CASE WHEN cnp.id > -1 THEN cnp.label ELSE '' END,
393                 cn.label,
394                 CASE WHEN cns.id > -1 THEN cns.label ELSE '' END,
395                 cp.status,
396                 count(cp.id)
397           FROM  $cp_table cp,
398             $cn_table cn,
399             $cns_table cns,
400             $cnp_table cnp,
401             $cl_table cl,
402             $cs_table cs,
403             $descendants d
404           WHERE cn.record = ?
405             AND cnp.id = cn.prefix
406             AND cns.id = cn.suffix
407             AND cp.call_number = cn.id
408             AND cp.location = cl.id
409             AND cp.circ_lib = d.id
410             AND cp.status = cs.id
411             AND cl.opac_visible IS TRUE
412             AND cp.opac_visible IS TRUE
413             AND cp.deleted IS FALSE
414             AND cs.opac_visible IS TRUE
415           GROUP BY 1,2,3,4,5;
416     SQL
417
418     my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
419     $sth->execute($ou, $depth, "$rec" );
420
421     my %data = ();
422     for my $row (@{$sth->fetchall_arrayref}) {
423         $data{$$row[0]}{$$row[1]}{$$row[2]}{$$row[3]}{$$row[4]} += $$row[5];
424     }
425     
426     for my $ou (keys %data) {
427         for my $cn_prefix (keys %{$data{$ou}}) {
428             for my $cn (keys %{$data{$ou}{$cn_prefix}}) {
429                 for my $cn_suffix (keys %{$data{$ou}{$cn_prefix}{$cn}}) {
430                     $client->respond( [$ou, $cn_prefix, $cn, $cn_suffix, $data{$ou}{$cn}{$cn_prefix}{$cn}{$cn_suffix}] );
431                 }
432             }
433         }
434     }
435     return undef;
436 }
437 __PACKAGE__->register_method(
438     api_name    => 'open-ils.storage.biblio.record_entry.status_copy_count',
439     method      => 'record_copy_status_count',
440     api_level   => 1,
441     stream      => 1,
442     cachable    => 1,
443 );
444
445
446 sub record_copy_status_location_count {
447     my $self = shift;
448     my $client = shift;
449
450     my $rec = shift;
451     my $ou = shift || 1;
452     my $depth = shift || 0;
453
454
455     my $descendants = "actor.org_unit_descendants(?,?)";
456
457     my $cn_table = asset::call_number->table;
458     my $cnp_table = asset::call_number_prefix->table;
459     my $cns_table = asset::call_number_suffix->table;
460     my $cp_table = asset::copy->table;
461     my $cl_table = asset::copy_location->table;
462     my $cs_table = config::copy_status->table;
463
464     # FIXME using oils_i18n_xlate here is exposing a hitherto unexposed
465     # implementation detail of json_query; doing it this way because
466     # json_query currently doesn't grok joining a function to tables
467     my $sql = <<"    SQL";
468
469         SELECT  cp.circ_lib,
470                 CASE WHEN cnp.id > -1 THEN cnp.label ELSE '' END,
471                 cn.label,
472                 CASE WHEN cns.id > -1 THEN cns.label ELSE '' END,
473                 oils_i18n_xlate('asset.copy_location', 'acpl', 'name', 'id', cl.id::TEXT, ?),
474                 cp.status,
475                 count(cp.id)
476           FROM  $cp_table cp,
477             $cn_table cn,
478             $cns_table cns,
479             $cnp_table cnp,
480             $cl_table cl,
481             $cs_table cs,
482             $descendants d
483           WHERE cn.record = ?
484             AND cnp.id = cn.prefix
485             AND cns.id = cn.suffix
486             AND cp.call_number = cn.id
487             AND cp.location = cl.id
488             AND cp.circ_lib = d.id
489             AND cp.status = cs.id
490             AND cl.opac_visible IS TRUE
491             AND cp.opac_visible IS TRUE
492             AND cp.deleted IS FALSE
493             AND cs.opac_visible IS TRUE
494           GROUP BY 1,2,3,4,5,6;
495     SQL
496
497     my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
498     my $ses_locale = $client->session ? $client->session->session_locale : 'en-US';
499     $sth->execute($ses_locale, $ou, $depth, "$rec" );
500
501     my %data = ();
502     for my $row (@{$sth->fetchall_arrayref}) {
503         $data{$$row[0]}{$$row[1]}{$$row[2]}{$$row[3]}{$$row[4]}{$$row[5]} += $$row[6];
504     }
505     
506     for my $ou (keys %data) {
507         for my $cn_prefix (keys %{$data{$ou}}) {
508             for my $cn (keys %{$data{$ou}{$cn_prefix}}) {
509                 for my $cn_suffix (keys %{$data{$ou}{$cn_prefix}{$cn}}) {
510                     for my $cl (keys %{$data{$ou}{$cn_prefix}{$cn}{$cn_suffix}}) {
511                         $client->respond( [$ou, $cn_prefix, $cn, $cn_suffix, $cl, $data{$ou}{$cn_prefix}{$cn}{$cn_suffix}{$cl}] );
512                     }
513                 }
514             }
515         }
516     }
517     return undef;
518 }
519 __PACKAGE__->register_method(
520     api_name    => 'open-ils.storage.biblio.record_entry.status_copy_location_count',
521     method      => 'record_copy_status_location_count',
522     api_level   => 1,
523     stream      => 1,
524     cachable    => 1,
525 );
526
527 1;