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