sped up page_down by about 20%
[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
255                 my $cp_fm = $cp->to_fieldmapper;
256                 $cp_fm->circ_lib( $cp->circ_lib->to_fieldmapper );
257                 $cp_fm->location( $cp->location->to_fieldmapper );
258                 $cp_fm->status( $cp->status->to_fieldmapper );
259                 $cp_fm->stat_cat_entries( [ map { $_->to_fieldmapper } $cp->stat_cat_entries ] );
260
261                 $client->respond( $cp_fm );
262         }
263
264         return undef;
265 }
266 __PACKAGE__->register_method(
267         api_name        => 'open-ils.storage.fleshed.asset.copy.batch.retrieve',
268         method          => 'fleshed_copy',
269         argc            => 1,
270         stream          => 1,
271 );
272 __PACKAGE__->register_method(
273         api_name        => 'open-ils.storage.fleshed.asset.copy.retrieve',
274         method          => 'fleshed_copy',
275         argc            => 1,
276 );
277
278 sub fleshed_copy_by_barcode {
279         my $self = shift;
280         my $client = shift;
281         my $bc = ''.shift;
282
283         my ($cp) = asset::copy->search( { barcode => $bc } );
284
285         return undef unless ($cp);
286
287         my $cp_fm = $cp->to_fieldmapper;
288         $cp_fm->circ_lib( $cp->circ_lib->to_fieldmapper );
289         $cp_fm->location( $cp->location->to_fieldmapper );
290         $cp_fm->status( $cp->status->to_fieldmapper );
291
292         return $cp_fm;
293 }       
294 __PACKAGE__->register_method(
295         api_name        => 'open-ils.storage.fleshed.asset.copy.search.barcode',
296         method          => 'fleshed_copy_by_barcode',
297         argc            => 1,
298         stream          => 1,
299 );
300
301 #XXX Fix stored proc calls
302 sub ranged_asset_stat_cat {
303         my $self = shift;
304         my $client = shift;
305         my $ou = ''.shift();
306
307         return undef unless ($ou);
308         my $s_table = asset::stat_cat->table;
309
310         my $select = <<"        SQL";
311                 SELECT  s.*
312                   FROM  $s_table s
313                         JOIN actor.org_unit_full_path(?) p ON (p.id = s.owner)
314                   ORDER BY name
315         SQL
316
317         $fleshed = 0;
318         $fleshed = 1 if ($self->api_name =~ /fleshed/o);
319
320         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
321         $sth->execute($ou);
322
323         for my $sc ( map { asset::stat_cat->construct($_) } $sth->fetchall_hash ) {
324                 my $sc_fm = $sc->to_fieldmapper;
325                 $sc_fm->entries(
326                         [ $self->method_lookup( 'open-ils.storage.ranged.asset.stat_cat_entry.search.stat_cat' )->run($ou,$sc->id) ]
327                 ) if ($fleshed);
328                 $client->respond( $sc_fm );
329         }
330
331         return undef;
332 }
333 __PACKAGE__->register_method(
334         api_name        => 'open-ils.storage.ranged.fleshed.asset.stat_cat.all',
335         api_level       => 1,
336         stream          => 1,
337         method          => 'ranged_asset_stat_cat',
338 );
339
340 __PACKAGE__->register_method(
341         api_name        => 'open-ils.storage.ranged.asset.stat_cat.all',
342         api_level       => 1,
343         stream          => 1,
344         method          => 'ranged_asset_stat_cat',
345 );
346
347
348 #XXX Fix stored proc calls
349 sub multiranged_asset_stat_cat {
350         my $self = shift;
351         my $client = shift;
352         my $ous = shift;
353
354         return undef unless (defined($ous) and @$ous);
355         my $s_table = asset::stat_cat->table;
356
357         my $select = <<"        SQL";
358                 SELECT  s.*
359                   FROM  $s_table s
360                   WHERE s.owner IN ( XXX )
361                   ORDER BY name
362         SQL
363
364         my $collector = ' INTERSECT ';
365         my $entry_method = 'open-ils.storage.multiranged.intersect.asset.stat_cat_entry.search.stat_cat';
366         if ($self->api_name =~ /union/o) {
367                 $collector = ' UNION ';
368                 $entry_method = 'open-ils.storage.multiranged.union.asset.stat_cat_entry.search.stat_cat';
369         }
370
371         my $binds = join($collector, map { 'SELECT id FROM actor.org_unit_full_path(?)' } grep {defined} @$ous);
372         $select =~ s/XXX/$binds/so;
373         
374         $fleshed = 0;
375         $fleshed = 1 if ($self->api_name =~ /fleshed/o);
376
377         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
378         $sth->execute(map { "$_" } grep {defined} @$ous);
379
380         for my $sc ( map { asset::stat_cat->construct($_) } $sth->fetchall_hash ) {
381                 my $sc_fm = $sc->to_fieldmapper;
382                 $sc_fm->entries(
383                         [ $self->method_lookup( $entry_method )->run($ous, $sc->id) ]
384                 ) if ($fleshed);
385                 $client->respond( $sc_fm );
386         }
387
388         return undef;
389 }
390 __PACKAGE__->register_method(
391         api_name        => 'open-ils.storage.multiranged.intersect.fleshed.asset.stat_cat.all',
392         api_level       => 1,
393         stream          => 1,
394         method          => 'multiranged_asset_stat_cat',
395 );
396 __PACKAGE__->register_method(
397         api_name        => 'open-ils.storage.multiranged.union.fleshed.asset.stat_cat.all',
398         api_level       => 1,
399         stream          => 1,
400         method          => 'multiranged_asset_stat_cat',
401 );
402
403 #XXX Fix stored proc calls
404 sub ranged_asset_stat_cat_entry {
405         my $self = shift;
406         my $client = shift;
407         my $ou = ''.shift();
408         my $sc = ''.shift();
409
410         return undef unless ($ou);
411         my $s_table = asset::stat_cat_entry->table;
412
413         my $select = <<"        SQL";
414                 SELECT  s.*
415                   FROM  $s_table s
416                         JOIN actor.org_unit_full_path(?) p ON (p.id = s.owner)
417                   WHERE stat_cat = ?
418                   ORDER BY name
419         SQL
420
421         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
422         $sth->execute($ou,$sc);
423
424         for my $sce ( map { asset::stat_cat_entry->construct($_) } $sth->fetchall_hash ) {
425                 $client->respond( $sce->to_fieldmapper );
426         }
427
428         return undef;
429 }
430 __PACKAGE__->register_method(
431         api_name        => 'open-ils.storage.ranged.asset.stat_cat_entry.search.stat_cat',
432         api_level       => 1,
433         stream          => 1,
434         method          => 'ranged_asset_stat_cat_entry',
435 );
436
437 #XXX Fix stored proc calls
438 sub multiranged_asset_stat_cat_entry {
439         my $self = shift;
440         my $client = shift;
441         my $ous = shift;
442         my $sc = ''.shift();
443
444         return undef unless (defined($ous) and @$ous);
445         my $s_table = asset::stat_cat_entry->table;
446
447         my $collector = ' INTERSECT ';
448         $collector = ' UNION ' if ($self->api_name =~ /union/o);
449
450         my $select = <<"        SQL";
451                 SELECT  s.*
452                   FROM  $s_table s
453                   WHERE s.owner IN ( XXX ) and s.stat_cat = ?
454                   ORDER BY value
455         SQL
456
457         my $binds = join($collector, map { 'SELECT id FROM actor.org_unit_full_path(?)' } grep {defined} @$ous);
458         $select =~ s/XXX/$binds/so;
459         
460         my $sth = asset::stat_cat->db_Main->prepare_cached($select);
461         $sth->execute(map {"$_"} @$ous,$sc);
462
463         for my $sce ( map { asset::stat_cat_entry->construct($_) } $sth->fetchall_hash ) {
464                 $client->respond( $sce->to_fieldmapper );
465         }
466
467         return undef;
468 }
469 __PACKAGE__->register_method(
470         api_name        => 'open-ils.storage.multiranged.intersect.asset.stat_cat_entry.search.stat_cat',
471         api_level       => 1,
472         stream          => 1,
473         method          => 'multiranged_asset_stat_cat_entry',
474 );
475 __PACKAGE__->register_method(
476         api_name        => 'open-ils.storage.multiranged.union.asset.stat_cat_entry.search.stat_cat',
477         api_level       => 1,
478         stream          => 1,
479         method          => 'multiranged_asset_stat_cat_entry',
480 );
481
482
483
484 1;