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