protecting against non-existant DB items
[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_by_barcode {
62         my $self = shift;
63         my $client = shift;
64
65         my $cn_table = asset::call_number->table;
66         my $cp_table = asset::copy->table;
67
68         my $id = ''.shift;
69         my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"   SQL", {}, $id );
70                 SELECT  cn.record
71                   FROM  $cn_table cn
72                         JOIN $cp_table cp ON (cp.call_number = cn.id)
73                   WHERE cp.barcode = ?
74         SQL
75
76         my $rec = biblio::record_entry->retrieve( $r );
77
78         return $rec->to_fieldmapper if ($rec);
79         return undef;
80 }
81 __PACKAGE__->register_method(
82         api_name        => 'open-ils.storage.biblio.record_entry.retrieve_by_barcode',
83         method          => 'record_by_barcode',
84         api_level       => 1,
85         cachable        => 1,
86 );
87
88 sub record_by_copy {
89         my $self = shift;
90         my $client = shift;
91
92         my $cn_table = asset::call_number->table;
93         my $cp_table = asset::copy->table;
94
95         my $id = ''.shift;
96         my ($r) = biblio::record_entry->db_Main->selectrow_array( <<"   SQL", {}, $id );
97                 SELECT  cn.record
98                   FROM  $cn_table cn
99                         JOIN $cp_table cp ON (cp.call_number = cn.id)
100                   WHERE cp.id = ?
101         SQL
102
103         my $rec = biblio::record_entry->retrieve( $r );
104         return undef unless ($rec)
105
106         my $r_fm = $rec->to_fieldmapper;
107         $r_fm->fixed_fields( $rec->record_descriptor->next->to_fieldmapper );
108
109         return $r_fm;
110 }
111 __PACKAGE__->register_method(
112         api_name        => 'open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy',
113         method          => 'record_by_copy',
114         api_level       => 1,
115         cachable        => 1,
116 );
117
118
119 =comment Old version
120
121 my $org_unit_lookup;
122 sub record_copy_count {
123         my $self = shift;
124         my $client = shift;
125         my $oid = shift;
126         my @recs = @_;
127
128         if ($self->api_name !~ /batch/o) {
129                 @recs = ($recs[0]);
130         }
131
132         throw OpenSRF::EX::InvalidArg ( "No org_unit id passed!" )
133                 unless ($oid);
134
135         throw OpenSRF::EX::InvalidArg ( "No record id passed!" )
136                 unless (@recs);
137
138         $org_unit_lookup ||= $self->method_lookup('open-ils.storage.direct.actor.org_unit.retrieve');
139         my ($org_unit) = $org_unit_lookup->run($oid);
140
141         # XXX Use descendancy tree here!!!
142         my $short_name_hack = $org_unit->shortname;
143         $short_name_hack = '' if (!$org_unit->parent_ou);
144         $short_name_hack .= '%';
145         # XXX Use descendancy tree here!!!
146
147         my $rec_list = join(',',@recs);
148
149         my $cp_table = asset::copy->table;
150         my $cn_table = asset::call_number->table;
151
152         my $select =<<" SQL";
153                 SELECT  count(cp.*) as copies
154                   FROM  $cn_table cn
155                         JOIN $cp_table cp ON (cp.call_number = cn.id)
156                   WHERE cn.owning_lib LIKE ? AND
157                         cn.record IN ($rec_list)
158         SQL
159
160         my $sth = asset::copy->db_Main->prepare_cached($select);
161         $sth->execute($short_name_hack);
162
163         my $results = $sth->fetchall_hashref('record');
164
165         $client->respond($$results{$_}{copies} || 0) for (@recs);
166
167         return undef;
168 }
169 __PACKAGE__->register_method(
170         method          => 'record_copy_count',
171         api_name        => 'open-ils.storage.direct.biblio.record_copy_count',
172         api_level       => 1,
173         argc            => 1,
174 );
175 __PACKAGE__->register_method(
176         method          => 'record_copy_count',
177         api_name        => 'open-ils.storage.direct.biblio.record_copy_count.batch',
178         api_level       => 1,
179         argc            => 1,
180         stream          => 1,
181 );
182
183 =cut
184
185 sub global_record_copy_count {
186         my $self = shift;
187         my $client = shift;
188
189         my $rec = shift;
190
191         my $cn_table = asset::call_number->table;
192         my $cp_table = asset::copy->table;
193         my $cl_table = asset::copy_location->table;
194         my $cs_table = config::copy_status->table;
195
196         my $copies_visible = 'AND cp.opac_visible IS TRUE AND cs.holdable IS TRUE AND cl.opac_visible IS TRUE';
197         $copies_visible = '' if ($self->api_name =~ /staff/o);
198
199         my $sql = <<"   SQL";
200
201                 SELECT  owning_lib, sum(avail), sum(tot)
202                   FROM  (
203                                 SELECT  cn.owning_lib, count(cp.id) as avail, 0 as tot
204                                   FROM  $cn_table cn
205                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
206                                         JOIN $cs_table cs ON (cs.id = cp.status)
207                                         JOIN $cl_table cl ON (cl.id = cp.location)
208                                   WHERE cn.record = ?
209                                         AND cp.status = 0
210                                         $copies_visible
211                                   GROUP BY 1
212                                                 UNION
213                                 SELECT  cn.owning_lib, 0 as avail, count(cp.id) as tot
214                                   FROM  $cn_table cn
215                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
216                                         JOIN $cs_table cs ON (cs.id = cp.status)
217                                         JOIN $cl_table cl ON (cl.id = cp.location)
218                                   WHERE cn.record = ?
219                                         $copies_visible
220                                   GROUP BY 1
221                         ) x
222                   GROUP BY 1
223         SQL
224
225         my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
226         $sth->execute("$rec", "$rec");
227
228         $client->respond( $_ ) for (@{$sth->fetchall_arrayref});
229         return undef;
230 }
231 __PACKAGE__->register_method(
232         api_name        => 'open-ils.storage.biblio.record_entry.global_copy_count',
233         method          => 'global_record_copy_count',
234         api_level       => 1,
235         stream          => 1,
236         cachable        => 1,
237 );
238 __PACKAGE__->register_method(
239         api_name        => 'open-ils.storage.biblio.record_entry.global_copy_count.staff',
240         method          => 'global_record_copy_count',
241         api_level       => 1,
242         stream          => 1,
243         cachable        => 1,
244 );
245
246 sub record_copy_status_count {
247         my $self = shift;
248         my $client = shift;
249
250         my $rec = shift;
251
252         my $cn_table = asset::call_number->table;
253         my $cp_table = asset::copy->table;
254         my $cl_table = asset::copy_location->table;
255         my $cs_table = config::copy_status->table;
256
257         my $sql = <<"   SQL";
258
259                 SELECT  cp.circ_lib, cn.label, cp.status, count(cp.id)
260                   FROM  $cp_table cp,
261                         $cn_table cn,
262                         $cl_table cl,
263                         $cs_table cs
264                   WHERE cn.record = ?
265                         AND cp.call_number = cn.id
266                         AND cp.location = cl.id
267                         AND cp.status = cs.id
268                         AND cl.opac_visible IS TRUE
269                         AND cp.opac_visible IS TRUE
270                         AND cs.holdable
271                   GROUP BY 1,2,3
272                   ORDER BY 1,2,3;
273         SQL
274
275         my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
276         $sth->execute("$rec");
277
278         my ($ou,$cn) = (0,'');
279         my %data = ();
280         for my $row (@{$sth->fetchall_arrayref}) {
281                 if ($ou and $ou ne $$row[0]) {
282                         my $i = 0;
283                         $client->respond( [$ou, $cn, {%data}] );
284                         %data = ();
285                 }
286                 ($ou,$cn) = ($$row[0],$$row[1]);
287                 $data{$$row[2]} = $$row[3];
288         }
289         return [$ou, $cn, {%data}] if ($ou);
290         return undef;
291 }
292 __PACKAGE__->register_method(
293         api_name        => 'open-ils.storage.biblio.record_entry.status_copy_count',
294         method          => 'record_copy_status_count',
295         api_level       => 1,
296         stream          => 1,
297         cachable        => 1,
298 );
299
300 1;