users now require permission to create containers -> bookbags
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Actor / Container.pm
1 package OpenILS::Application::Actor::Container;
2 use base 'OpenSRF::Application';
3 use strict; use warnings;
4 use OpenILS::Application::AppUtils;
5 use OpenILS::Perm;
6 use Data::Dumper;
7 use OpenSRF::EX qw(:try);
8 use OpenILS::Utils::Fieldmapper;
9
10 my $apputils = "OpenILS::Application::AppUtils";
11 my $U = $apputils;
12 my $logger = "OpenSRF::Utils::Logger";
13
14 sub initialize { return 1; }
15
16 my $svc = 'open-ils.storage';
17 my $meth = 'open-ils.storage.direct.container';
18 my %types;
19 $types{'biblio'} = "$meth.biblio_record_entry_bucket";
20 $types{'callnumber'} = "$meth.call_number_bucket";
21 $types{'copy'} = "$meth.copy_bucket";
22 $types{'user'} = "$meth.user_bucket";
23 my $event;
24
25 sub _sort_buckets {
26         my $buckets = shift;
27         return $buckets unless ($buckets && $buckets->[0]);
28         return [ sort { $a->name cmp $b->name } @$buckets ];
29 }
30
31 __PACKAGE__->register_method(
32         method  => "bucket_retrieve_all",
33         api_name        => "open-ils.actor.container.all.retrieve_by_user",
34         notes           => <<"  NOTES");
35                 Retrieves all un-fleshed buckets assigned to given user 
36                 PARAMS(authtoken, bucketOwnerId)
37                 If requestor ID is different than bucketOwnerId, requestor must have
38                 VIEW_CONTAINER permissions.
39         NOTES
40
41 sub bucket_retrieve_all {
42         my($self, $client, $authtoken, $userid) = @_;
43
44         my( $staff, $evt ) = $apputils->checkses($authtoken);
45         return $evt if $evt;
46
47         my( $user, $e ) = $apputils->checkrequestor( $staff, $userid, 'VIEW_CONTAINER');
48         return $e if $e;
49
50         $logger->debug("User " . $staff->id . 
51                 " retrieving all buckets for user $userid");
52
53         my %buckets;
54
55         $buckets{$_} = $apputils->simplereq( 
56                 $svc, $types{$_} . ".search.owner.atomic", $userid ) for keys %types;
57
58         return \%buckets;
59 }
60
61 __PACKAGE__->register_method(
62         method  => "bucket_flesh",
63         api_name        => "open-ils.actor.container.flesh",
64         argc            => 3, 
65         notes           => <<"  NOTES");
66                 Fleshes a bucket by id
67                 PARAMS(authtoken, bucketClass, bucketId)
68                 bucketclasss include biblio, callnumber, copy, and user.  
69                 bucketclass defaults to biblio.
70                 If requestor ID is different than bucketOwnerId, requestor must have
71                 VIEW_CONTAINER permissions.
72         NOTES
73
74 sub bucket_flesh {
75
76         my($self, $client, $authtoken, $class, $bucket) = @_;
77
78         my( $staff, $evt ) = $apputils->checkses($authtoken);
79         return $evt if $evt;
80
81         $logger->debug("User " . $staff->id . " retrieving bucket $bucket");
82
83         my $meth = $types{$class};
84
85         my $bkt = $apputils->simplereq( $svc, "$meth.retrieve", $bucket );
86         if(!$bkt) {return undef};
87
88         if(!$bkt->pub) {
89                 my( $user, $e ) = $apputils->checkrequestor( $staff, $bkt->owner, 'VIEW_CONTAINER' );
90                 return $e if $e;
91         }
92
93         $bkt->items( $apputils->simplereq( $svc,
94                 "$meth"."_item.search.bucket.atomic", $bucket ) );
95
96         return $bkt;
97 }
98
99
100 __PACKAGE__->register_method(
101         method  => "bucket_flesh_public",
102         api_name        => "open-ils.actor.container.public.flesh",
103         argc            => 3, 
104         notes           => <<"  NOTES");
105                 Fleshes a bucket by id
106                 PARAMS(authtoken, bucketClass, bucketId)
107                 bucketclasss include biblio, callnumber, copy, and user.  
108                 bucketclass defaults to biblio.
109                 If requestor ID is different than bucketOwnerId, requestor must have
110                 VIEW_CONTAINER permissions.
111         NOTES
112
113 sub bucket_flesh_public {
114
115         my($self, $client, $class, $bucket) = @_;
116
117         my $meth = $types{$class};
118         my $bkt = $apputils->simplereq( $svc, "$meth.retrieve", $bucket );
119         return undef unless ($bkt and $bkt->pub);
120
121         $bkt->items( $apputils->simplereq( $svc,
122                 "$meth"."_item.search.bucket.atomic", $bucket ) );
123
124         return $bkt;
125 }
126
127
128 __PACKAGE__->register_method(
129         method  => "bucket_retrieve_class",
130         api_name        => "open-ils.actor.container.retrieve_by_class",
131         argc            => 3, 
132         notes           => <<"  NOTES");
133                 Retrieves all un-fleshed buckets by class assigned to given user 
134                 PARAMS(authtoken, bucketOwnerId, class [, type])
135                 class can be one of "biblio", "callnumber", "copy", "user"
136                 The optional "type" parameter allows you to limit the search by 
137                 bucket type.  
138                 If bucketOwnerId is not defined, the authtoken is used as the
139                 bucket owner.
140                 If requestor ID is different than bucketOwnerId, requestor must have
141                 VIEW_CONTAINER permissions.
142         NOTES
143
144 sub bucket_retrieve_class {
145         my( $self, $client, $authtoken, $userid, $class, $type ) = @_;
146
147         my( $staff, $user, $evt ) = 
148                 $apputils->checkses_requestor( $authtoken, $userid, 'VIEW_CONTAINER' );
149         return $evt if $evt;
150
151         $logger->debug("User " . $staff->id . 
152                 " retrieving buckets for user $userid [class=$class, type=$type]");
153
154         my $meth = $types{$class} . ".search_where.atomic";
155         my $buckets;
156
157         if( $type ) {
158                 $buckets = $apputils->simplereq( $svc, 
159                         $meth, { owner => $userid, btype => $type } );
160         } else {
161                 $logger->debug("Grabbing buckets by class $class: $svc : $meth :  {owner => $userid}");
162                 $buckets = $apputils->simplereq( $svc, $meth, { owner => $userid } );
163         }
164
165         return _sort_buckets($buckets);
166 }
167
168 __PACKAGE__->register_method(
169         method  => "bucket_create",
170         api_name        => "open-ils.actor.container.create",
171         notes           => <<"  NOTES");
172                 Creates a new bucket object.  If requestor is different from
173                 bucketOwner, requestor needs CREATE_CONTAINER permissions
174                 PARAMS(authtoken, bucketObject);
175                 Returns the new bucket object
176         NOTES
177
178 sub bucket_create {
179         my( $self, $client, $authtoken, $class, $bucket ) = @_;
180
181         my( $staff, $target, $evt ) = 
182                 $apputils->checkses_requestor( 
183                         $authtoken, $bucket->owner, 'CREATE_CONTAINER' );
184         return $evt if $evt;
185
186         if( $staff->id eq $target->id ) {
187                 $evt = $U->check_perms($target->id, $target->home_ou, 'CREATE_MY_CONTAINER');
188                 return $evt if $evt;
189         }
190
191         $logger->activity( "User " . $staff->id . 
192                 " creating a new container for user " . $bucket->owner );
193
194         $bucket->clear_id;
195         $logger->debug("Creating new container object: " . Dumper($bucket));
196
197         my $method = $types{$class} . ".create";
198         my $id = $apputils->simplereq( $svc, $method, $bucket );
199
200         $logger->debug("Creatined new container with id $id");
201
202         if(!$id) { throw OpenSRF::EX 
203                 ("Unable to create new bucket object"); }
204
205         return $id;
206 }
207
208
209 __PACKAGE__->register_method(
210         method  => "bucket_delete",
211         api_name        => "open-ils.actor.container.delete",
212         notes           => <<"  NOTES");
213                 Deletes a bucket object.  If requestor is different from
214                 bucketOwner, requestor needs DELETE_CONTAINER permissions
215                 PARAMS(authtoken, class, bucketId);
216                 Returns the new bucket object
217         NOTES
218
219 sub bucket_delete {
220         my( $self, $client, $authtoken, $class, $bucketid ) = @_;
221
222         my( $bucket, $staff, $target, $evt );
223
224         ( $bucket, $evt ) = $apputils->fetch_container($bucketid, $class);
225         return $evt if $evt;
226
227         ( $staff, $target, $evt ) = $apputils->checkses_requestor( 
228                 $authtoken, $bucket->owner, 'DELETE_CONTAINER' );
229         return $evt if $evt;
230
231         $logger->activity( "User " . $staff->id . 
232                 " deleting container $bucketid for user " . $bucket->owner );
233
234         my $method = $types{$class} . ".delete";
235         my $resp = $apputils->simplereq( $svc, $method, $bucketid );
236
237         throw OpenSRF::EX ("Unable to create new bucket object") unless $resp;
238         return $resp;
239 }
240
241
242 __PACKAGE__->register_method(
243         method  => "item_create",
244         api_name        => "open-ils.actor.container.item.create",
245         notes           => <<"  NOTES");
246                 PARAMS(authtoken, class, item)
247         NOTES
248
249 sub item_create {
250         my( $self, $client, $authtoken, $class, $item ) = @_;
251         my( $bucket, $staff, $target, $evt);
252
253         ( $bucket, $evt ) = $apputils->fetch_container($item->bucket, $class);
254         return $evt if $evt;
255
256         ( $staff, $target, $evt ) = $apputils->checkses_requestor( 
257                 $authtoken, $bucket->owner, 'CREATE_CONTAINER_ITEM' );
258         return $evt if $evt;
259
260         $logger->activity( "User " . $staff->id . 
261                 " creating container item for bucket " . $item->bucket . " and user " . $bucket->owner );
262
263         my $method = $types{$class} . "_item.create";
264         my $resp = $apputils->simplereq( $svc, $method, $item );
265
266         return $U->DB_UPDATE_FAILED($item) unless $resp;
267         return $resp;
268 }
269
270
271
272 __PACKAGE__->register_method(
273         method  => "item_delete",
274         api_name        => "open-ils.actor.container.item.delete",
275         notes           => <<"  NOTES");
276                 PARAMS(authtoken, class, itemId)
277         NOTES
278
279 sub item_delete {
280         my( $self, $client, $authtoken, $class, $itemid ) = @_;
281         my( $bucket, $item, $staff, $target, $evt);
282
283         
284         ( $item, $evt ) = $apputils->fetch_container_item( $itemid, $class );
285         return $evt if $evt;
286
287         ( $bucket, $evt ) = $apputils->fetch_container($item->bucket, $class);
288         return $evt if $evt;
289
290         ( $staff, $target, $evt ) = $apputils->checkses_requestor( 
291                 $authtoken, $bucket->owner, 'DELETE_CONTAINER_ITEM' );
292         return $evt if $evt;
293
294         $logger->activity( "User " . $staff->id . 
295                 " deleting continer item  $itemid for user " . $bucket->owner );
296
297         my $method = $types{$class} . "_item.delete";
298         my $resp = $apputils->simplereq( $svc, $method, $itemid );
299
300         throw OpenSRF::EX ("Unable to delete container item") unless $resp;
301         return $resp;
302 }
303
304 __PACKAGE__->register_method(
305         method  => 'full_delete',
306         api_name        => 'open-ils.actor.container.full_delete',
307         notes           => "Complety removes a container including all attached items",
308 );      
309
310 sub full_delete {
311         my( $self, $client, $authtoken, $class, $containerId ) = @_;
312         my( $staff, $target, $container, $evt);
313
314         ( $container, $evt ) = $apputils->fetch_container($containerId, $class);
315         return $evt if $evt;
316
317         ( $staff, $target, $evt ) = $apputils->checkses_requestor( 
318                 $authtoken, $container->owner, 'DELETE_CONTAINER' );
319         return $evt if $evt;
320
321         $logger->activity("User " . $staff->id . " deleting full container $containerId");
322
323         my $meth = $types{$class};
324         my $items = $apputils->simplereq( $svc, "$meth"."_item.search.bucket.atomic", $containerId );
325
326         $self->item_delete( $client, $authtoken, $class, $_->id ) for @$items;
327
328         $meth = $types{$class} . ".delete";
329         return $apputils->simplereq( $svc, $meth, $containerId );
330 }
331
332 __PACKAGE__->register_method(
333         method          => 'container_update',
334         api_name                => 'open-ils.actor.container.update',
335         signature       => q/
336                 Updates the given container item.
337                 @param authtoken The login session key
338                 @param class The container class
339                 @param container The container item
340                 @return true on success, 0 on no update, Event on error
341                 /
342 );
343
344 sub container_update {
345         my( $self, $conn, $authtoken, $class, $container )  = @_;
346
347         my( $staff, $target, $dbcontainer, $evt);
348
349         ( $dbcontainer, $evt ) = $apputils->fetch_container($container->id, $class);
350         return $evt if $evt;
351
352         ( $staff, $target, $evt ) = $apputils->checkses_requestor( 
353                 $authtoken, $dbcontainer->owner, 'UPDATE_CONTAINER' );
354         return $evt if $evt;
355
356         $logger->activity("User " . $staff->id . " updating container ". $container->id);
357
358         my $meth = $types{$class}.".update";
359         return $U->storagereq($meth, $container);
360 }
361
362
363
364
365 1;
366
367