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