protecting against non-existant DB items
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Publisher / asset.pm
1 package OpenILS::Application::Storage::Publisher::asset;
2 use base qw/OpenILS::Application::Storage/;
3 #use OpenILS::Application::Storage::CDBI::asset;
4 #use OpenSRF::Utils::Logger qw/:level/;
5 #use OpenILS::Utils::Fieldmapper;
6 #
7 #my $log = 'OpenSRF::Utils::Logger';
8
9 # XXX
10 # see /home/miker/cn_browse-test.sql for page up and down sql ...
11 # XXX
12
13 sub cn_browse_pagedown {
14         my $self = shift;
15         my $client = shift;
16
17         my %args = @_;
18
19         my $cn = uc($args{label});
20         my $org = $args{org_unit};
21         my $depth = $args{depth};
22         my $boundry_id = $args{boundry_id};
23         my $size = $args{page_size} || 20;
24         $size = int($size);
25
26         my $table = asset::call_number->table;
27
28         my $descendants = "actor.org_unit_descendants($org)";
29         if (defined $depth) {
30                 $descendants = "actor.org_unit_descendants($org,$depth)";
31         }
32
33         my $sql = <<"   SQL";
34                 select
35                         cn.label,
36                         cn.owning_lib,
37                         cn.record,
38                         cn.id
39                 from
40                         $table cn
41                         join $descendants d
42                                 on (d.id = cn.owning_lib)
43                 where
44                         upper(label) > ?
45                         or ( cn.id > ? and upper(label) = ? )
46                 order by upper(label), 4, 2
47                 limit $size;
48         SQL
49
50         my $sth = asset::call_number->db_Main->prepare($sql);
51         $sth->execute($cn, $boundry_id, $cn);
52         while ( my @row = $sth->fetchrow_array ) {
53                 $client->respond([@row]);
54         }
55         $sth->finish;
56
57         return undef;
58 }
59 __PACKAGE__->register_method(
60         method          => 'cn_browse_pagedown',
61         api_name        => 'open-ils.storage.asset.call_number.browse.page_down',
62         argc            => 4,
63         stream          => 1,
64 );
65
66 sub cn_browse_pageup {
67         my $self = shift;
68         my $client = shift;
69
70         my %args = @_;
71
72         my $cn = uc($args{label});
73         my $org = $args{org_unit};
74         my $depth = $args{depth};
75         my $boundry_id = $args{boundry_id};
76         my $size = $args{page_size} || 20;
77         $size = int($size);
78
79         my $table = asset::call_number->table;
80
81         my $descendants = "actor.org_unit_descendants($org)";
82         if (defined $depth) {
83                 $descendants = "actor.org_unit_descendants($org,$depth)";
84         }
85
86         my $sql = <<"   SQL";
87                 select * from (
88                         select
89                                 cn.label,
90                                 cn.owning_lib,
91                                 cn.record,
92                                 cn.id
93                         from
94                                 $table cn
95                                 join $descendants d
96                                         on (d.id = cn.owning_lib)
97                         where
98                                 upper(label) < ?
99                                 or ( cn.id < ? and upper(label) = ? )
100                         order by upper(label) desc, 4 desc, 2 desc
101                         limit $size
102                 ) as bar
103                 order by 1,4,2;
104         SQL
105
106         my $sth = asset::call_number->db_Main->prepare($sql);
107         $sth->execute($cn, $boundry_id, $cn);
108         while ( my @row = $sth->fetchrow_array ) {
109                 $client->respond([@row]);
110         }
111         $sth->finish;
112
113         return undef;
114 }
115 __PACKAGE__->register_method(
116         method          => 'cn_browse_pageup',
117         api_name        => 'open-ils.storage.asset.call_number.browse.page_up',
118         argc            => 4,
119         stream          => 1,
120 );
121
122 sub cn_browse_target {
123         my $self = shift;
124         my $client = shift;
125
126         my %args = @_;
127
128         my $cn = uc($args{label});
129         my $org = $args{org_unit};
130         my $depth = $args{depth};
131         my $size = $args{page_size} || 20;
132         my $topsize = $size / 2;
133         $topsize = int($topsize);
134         $bottomsize = $size - $topsize;
135
136         my $table = asset::call_number->table;
137
138         my $descendants = "actor.org_unit_descendants($org)";
139         if (defined $depth) {
140                 $descendants = "actor.org_unit_descendants($org,$depth)";
141         }
142
143         my $top_sql = <<"       SQL";
144                 select * from (
145                         select
146                                 cn.label,
147                                 cn.owning_lib,
148                                 cn.record,
149                                 cn.id
150                         from
151                                 $table cn
152                                 join $descendants d
153                                         on (d.id = cn.owning_lib)
154                         where
155                                 upper(label) < ?
156                         order by upper(label) desc, 4 desc, 2 desc
157                         limit $topsize
158                 ) as bar
159                 order by 1,4,2;
160         SQL
161
162         my $bottom_sql = <<"    SQL";
163                 select
164                         cn.label,
165                         cn.owning_lib,
166                         cn.record,
167                         cn.id
168                 from
169                         $table cn
170                         join $descendants d
171                                 on (d.id = cn.owning_lib)
172                 where
173                         upper(label) >= ?
174                 order by upper(label),4,2
175                 limit $bottomsize;
176         SQL
177
178         my $sth = asset::call_number->db_Main->prepare($top_sql);
179         $sth->execute($cn);
180         while ( my @row = $sth->fetchrow_array ) {
181                 $client->respond([@row]);
182         }
183         $sth->finish;
184
185         $sth = asset::call_number->db_Main->prepare($bottom_sql);
186         $sth->execute($cn);
187         while ( my @row = $sth->fetchrow_array ) {
188                 $client->respond([@row]);
189         }
190         $sth->finish;
191
192         return undef;
193 }
194 __PACKAGE__->register_method(
195         method          => 'cn_browse_target',
196         api_name        => 'open-ils.storage.asset.call_number.browse.target',
197         argc            => 4,
198         stream          => 1,
199 );
200
201
202 sub copy_proximity {
203         my $self = shift;
204         my $client = shift;
205
206         my $cp = shift;
207         my $org = shift;
208
209         return unless ($cp && $org);
210
211         $cp = $cp->id if (ref $cp);
212         $cp = asset::copy->retrieve($cp);
213         return 999 unless $copy;
214         my $ol = $cp->call_number->owning_lib;
215
216         return asset::copy->db_Main->selectcol_arrayref('SELECT actor.org_unit_proximity(?,?)',{},"$ol","$org")->[0];
217 }
218 __PACKAGE__->register_method(
219         method          => 'copy_proximity',
220         api_name        => 'open-ils.storage.asset.copy.proximity',
221         argc            => 2,
222         stream          => 1,
223 );
224
225 sub asset_copy_location_all {
226         my $self = shift;
227         my $client = shift;
228
229         for my $rec ( asset::copy_location->retrieve_all ) {
230                 $client->respond( $rec->to_fieldmapper );
231         }
232
233         return undef;
234 }
235 __PACKAGE__->register_method(
236         method          => 'asset_copy_location_all',
237         api_name        => 'open-ils.storage.direct.asset.copy_location.retrieve.all',
238         argc            => 0,
239         stream          => 1,
240 );
241
242 sub fleshed_copy {
243         my $self = shift;
244         my $client = shift;
245         my @ids = @_;
246
247         return undef unless (@ids);
248
249         @ids = ($ids[0]) unless ($self->api_name =~ /batch/o);
250
251         for my $id ( @ids ) {
252                 next unless $id;
253                 my $cp = asset::copy->retrieve($id);
254                 next unless $cp;
255
256                 my $cp_fm = $cp->to_fieldmapper;
257                 $cp_fm->circ_lib( $cp->circ_lib->to_fieldmapper );
258                 $cp_fm->location( $cp->location->to_fieldmapper );
259                 $cp_fm->status( $cp->status->to_fieldmapper );
260                 $cp_fm->stat_cat_entries( [ map { $_->to_fieldmapper } $cp->stat_cat_entries ] );
261
262                 $client->respond( $cp_fm );
263         }
264
265         return undef;
266 }
267 __PACKAGE__->register_method(
268         api_name        => 'open-ils.storage.fleshed.asset.copy.batch.retrieve',
269         method          => 'fleshed_copy',
270         argc            => 1,
271         stream          => 1,
272 );
273 __PACKAGE__->register_method(
274         api_name        => 'open-ils.storage.fleshed.asset.copy.retrieve',
275         method          => 'fleshed_copy',
276         argc            => 1,
277 );
278
279 sub fleshed_copy_by_barcode {
280         my $self = shift;
281         my $client = shift;
282         my $bc = ''.shift;
283
284         my ($cp) = asset::copy->search( { barcode => $bc } );
285
286         return undef unless ($cp);
287
288         my $cp_fm = $cp->to_fieldmapper;
289         $cp_fm->circ_lib( $cp->circ_lib->to_fieldmapper );
290         $cp_fm->location( $cp->location->to_fieldmapper );
291         $cp_fm->status( $cp->status->to_fieldmapper );
292
293         return $cp_fm;
294 }       
295 __PACKAGE__->register_method(
296         api_name        => 'open-ils.storage.fleshed.asset.copy.search.barcode',
297         method          => 'fleshed_copy_by_barcode',
298         argc            => 1,
299         stream          => 1,
300 );
301
302 #XXX Fix stored proc calls
303 sub ranged_asset_stat_cat {
304         my $self = shift;
305         my $client = shift;
306         my $ou = ''.shift();
307
308         return undef unless ($ou);
309         my $s_table = asset::stat_cat->table;
310
311         my $select = <<"        SQL";
312                 SELECT  s.*
313                   FROM  $s_table s
314                         JOIN actor.org_unit_full_path(?) p ON (p.id = s.owner)
315                   ORDER BY name
316         SQL
317
318         $fleshed = 0;
319         $fleshed = 1 if ($self->api_name =~ /fleshed/o);
320
321         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
322         $sth->execute($ou);
323
324         for my $sc ( map { asset::stat_cat->construct($_) } $sth->fetchall_hash ) {
325                 my $sc_fm = $sc->to_fieldmapper;
326                 $sc_fm->entries(
327                         [ $self->method_lookup( 'open-ils.storage.ranged.asset.stat_cat_entry.search.stat_cat' )->run($ou,$sc->id) ]
328                 ) if ($fleshed);
329                 $client->respond( $sc_fm );
330         }
331
332         return undef;
333 }
334 __PACKAGE__->register_method(
335         api_name        => 'open-ils.storage.ranged.fleshed.asset.stat_cat.all',
336         api_level       => 1,
337         stream          => 1,
338         method          => 'ranged_asset_stat_cat',
339 );
340
341 __PACKAGE__->register_method(
342         api_name        => 'open-ils.storage.ranged.asset.stat_cat.all',
343         api_level       => 1,
344         stream          => 1,
345         method          => 'ranged_asset_stat_cat',
346 );
347
348
349 #XXX Fix stored proc calls
350 sub multiranged_asset_stat_cat {
351         my $self = shift;
352         my $client = shift;
353         my $ous = shift;
354
355         return undef unless (defined($ous) and @$ous);
356         my $s_table = asset::stat_cat->table;
357
358         my $select = <<"        SQL";
359                 SELECT  s.*
360                   FROM  $s_table s
361                   WHERE s.owner IN ( XXX )
362                   ORDER BY name
363         SQL
364
365         my $collector = ' INTERSECT ';
366         my $entry_method = 'open-ils.storage.multiranged.intersect.asset.stat_cat_entry.search.stat_cat';
367         if ($self->api_name =~ /union/o) {
368                 $collector = ' UNION ';
369                 $entry_method = 'open-ils.storage.multiranged.union.asset.stat_cat_entry.search.stat_cat';
370         }
371
372         my $binds = join($collector, map { 'SELECT id FROM actor.org_unit_full_path(?)' } grep {defined} @$ous);
373         $select =~ s/XXX/$binds/so;
374         
375         $fleshed = 0;
376         $fleshed = 1 if ($self->api_name =~ /fleshed/o);
377
378         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
379         $sth->execute(map { "$_" } grep {defined} @$ous);
380
381         for my $sc ( map { asset::stat_cat->construct($_) } $sth->fetchall_hash ) {
382                 my $sc_fm = $sc->to_fieldmapper;
383                 $sc_fm->entries(
384                         [ $self->method_lookup( $entry_method )->run($ous, $sc->id) ]
385                 ) if ($fleshed);
386                 $client->respond( $sc_fm );
387         }
388
389         return undef;
390 }
391 __PACKAGE__->register_method(
392         api_name        => 'open-ils.storage.multiranged.intersect.fleshed.asset.stat_cat.all',
393         api_level       => 1,
394         stream          => 1,
395         method          => 'multiranged_asset_stat_cat',
396 );
397 __PACKAGE__->register_method(
398         api_name        => 'open-ils.storage.multiranged.union.fleshed.asset.stat_cat.all',
399         api_level       => 1,
400         stream          => 1,
401         method          => 'multiranged_asset_stat_cat',
402 );
403
404 #XXX Fix stored proc calls
405 sub ranged_asset_stat_cat_entry {
406         my $self = shift;
407         my $client = shift;
408         my $ou = ''.shift();
409         my $sc = ''.shift();
410
411         return undef unless ($ou);
412         my $s_table = asset::stat_cat_entry->table;
413
414         my $select = <<"        SQL";
415                 SELECT  s.*
416                   FROM  $s_table s
417                         JOIN actor.org_unit_full_path(?) p ON (p.id = s.owner)
418                   WHERE stat_cat = ?
419                   ORDER BY name
420         SQL
421
422         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
423         $sth->execute($ou,$sc);
424
425         for my $sce ( map { asset::stat_cat_entry->construct($_) } $sth->fetchall_hash ) {
426                 $client->respond( $sce->to_fieldmapper );
427         }
428
429         return undef;
430 }
431 __PACKAGE__->register_method(
432         api_name        => 'open-ils.storage.ranged.asset.stat_cat_entry.search.stat_cat',
433         api_level       => 1,
434         stream          => 1,
435         method          => 'ranged_asset_stat_cat_entry',
436 );
437
438 #XXX Fix stored proc calls
439 sub multiranged_asset_stat_cat_entry {
440         my $self = shift;
441         my $client = shift;
442         my $ous = shift;
443         my $sc = ''.shift();
444
445         return undef unless (defined($ous) and @$ous);
446         my $s_table = asset::stat_cat_entry->table;
447
448         my $collector = ' INTERSECT ';
449         $collector = ' UNION ' if ($self->api_name =~ /union/o);
450
451         my $select = <<"        SQL";
452                 SELECT  s.*
453                   FROM  $s_table s
454                   WHERE s.owner IN ( XXX ) and s.stat_cat = ?
455                   ORDER BY value
456         SQL
457
458         my $binds = join($collector, map { 'SELECT id FROM actor.org_unit_full_path(?)' } grep {defined} @$ous);
459         $select =~ s/XXX/$binds/so;
460         
461         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
462         $sth->execute(map {"$_"} @$ous,$sc);
463
464         for my $sce ( map { asset::stat_cat_entry->construct($_) } $sth->fetchall_hash ) {
465                 $client->respond( $sce->to_fieldmapper );
466         }
467
468         return undef;
469 }
470 __PACKAGE__->register_method(
471         api_name        => 'open-ils.storage.multiranged.intersect.asset.stat_cat_entry.search.stat_cat',
472         api_level       => 1,
473         stream          => 1,
474         method          => 'multiranged_asset_stat_cat_entry',
475 );
476 __PACKAGE__->register_method(
477         api_name        => 'open-ils.storage.multiranged.union.asset.stat_cat_entry.search.stat_cat',
478         api_level       => 1,
479         stream          => 1,
480         method          => 'multiranged_asset_stat_cat_entry',
481 );
482
483
484
485 1;