]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor/Container.pm
added event for duplicate bucket creation errors
[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 use OpenILS::Utils::CStoreEditor qw/:funcs/;
10
11 my $apputils = "OpenILS::Application::AppUtils";
12 my $U = $apputils;
13 my $logger = "OpenSRF::Utils::Logger";
14
15 sub initialize { return 1; }
16
17 my $svc = 'open-ils.cstore';
18 my $meth = 'open-ils.cstore.direct.container';
19 my %types;
20 $types{'biblio'} = "$meth.biblio_record_entry_bucket";
21 $types{'callnumber'} = "$meth.call_number_bucket";
22 $types{'copy'} = "$meth.copy_bucket";
23 $types{'user'} = "$meth.user_bucket";
24 my $event;
25
26 sub _sort_buckets {
27         my $buckets = shift;
28         return $buckets unless ($buckets && $buckets->[0]);
29         return [ sort { $a->name cmp $b->name } @$buckets ];
30 }
31
32 __PACKAGE__->register_method(
33         method  => "bucket_retrieve_all",
34         api_name        => "open-ils.actor.container.all.retrieve_by_user",
35         notes           => <<"  NOTES");
36                 Retrieves all un-fleshed buckets assigned to given user 
37                 PARAMS(authtoken, bucketOwnerId)
38                 If requestor ID is different than bucketOwnerId, requestor must have
39                 VIEW_CONTAINER permissions.
40         NOTES
41
42 sub bucket_retrieve_all {
43         my($self, $client, $authtoken, $userid) = @_;
44
45         my( $staff, $evt ) = $apputils->checkses($authtoken);
46         return $evt if $evt;
47
48         my( $user, $e ) = $apputils->checkrequestor( $staff, $userid, 'VIEW_CONTAINER');
49         return $e if $e;
50
51         $logger->debug("User " . $staff->id . 
52                 " retrieving all buckets for user $userid");
53
54         my %buckets;
55
56         $buckets{$_} = $apputils->simplereq( 
57                 $svc, $types{$_} . ".search.atomic", { owner => $userid } ) for keys %types;
58
59         return \%buckets;
60 }
61
62 __PACKAGE__->register_method(
63         method  => "bucket_flesh",
64         api_name        => "open-ils.actor.container.flesh",
65         argc            => 3, 
66         notes           => <<"  NOTES");
67                 Fleshes a bucket by id
68                 PARAMS(authtoken, bucketClass, bucketId)
69                 bucketclasss include biblio, callnumber, copy, and user.  
70                 bucketclass defaults to biblio.
71                 If requestor ID is different than bucketOwnerId, requestor must have
72                 VIEW_CONTAINER permissions.
73         NOTES
74
75 sub bucket_flesh {
76
77         my($self, $client, $authtoken, $class, $bucket) = @_;
78
79         my( $staff, $evt ) = $apputils->checkses($authtoken);
80         return $evt if $evt;
81
82         $logger->debug("User " . $staff->id . " retrieving bucket $bucket");
83
84         my $meth = $types{$class};
85
86         my $bkt = $apputils->simplereq( $svc, "$meth.retrieve", $bucket );
87         #if(!$bkt) {return undef};
88         return OpenILS::Event->new('CONTAINER_NOT_FOUND', payload=>$bucket) unless $bkt;
89
90         if(!$bkt->pub) {
91                 my( $user, $e ) = $apputils->checkrequestor( $staff, $bkt->owner, 'VIEW_CONTAINER' );
92                 return $e if $e;
93         }
94
95         $bkt->items( $apputils->simplereq( $svc,
96                 "$meth"."_item.search.atomic", { bucket => $bucket } ) );
97
98         return $bkt;
99 }
100
101
102 __PACKAGE__->register_method(
103         method  => "bucket_flesh_public",
104         api_name        => "open-ils.actor.container.public.flesh",
105         argc            => 3, 
106         notes           => <<"  NOTES");
107                 Fleshes a bucket by id
108                 PARAMS(authtoken, bucketClass, bucketId)
109                 bucketclasss include biblio, callnumber, copy, and user.  
110                 bucketclass defaults to biblio.
111                 If requestor ID is different than bucketOwnerId, requestor must have
112                 VIEW_CONTAINER permissions.
113         NOTES
114
115 sub bucket_flesh_public {
116
117         my($self, $client, $class, $bucket) = @_;
118
119         my $meth = $types{$class};
120         my $bkt = $apputils->simplereq( $svc, "$meth.retrieve", $bucket );
121         return undef unless ($bkt and $bkt->pub);
122
123         $bkt->items( $apputils->simplereq( $svc,
124                 "$meth"."_item.search.atomic", { bucket => $bucket } ) );
125
126         return $bkt;
127 }
128
129
130 __PACKAGE__->register_method(
131         method  => "bucket_retrieve_class",
132         api_name        => "open-ils.actor.container.retrieve_by_class",
133         argc            => 3, 
134         notes           => <<"  NOTES");
135                 Retrieves all un-fleshed buckets by class assigned to given user 
136                 PARAMS(authtoken, bucketOwnerId, class [, type])
137                 class can be one of "biblio", "callnumber", "copy", "user"
138                 The optional "type" parameter allows you to limit the search by 
139                 bucket type.  
140                 If bucketOwnerId is not defined, the authtoken is used as the
141                 bucket owner.
142                 If requestor ID is different than bucketOwnerId, requestor must have
143                 VIEW_CONTAINER permissions.
144         NOTES
145
146 sub bucket_retrieve_class {
147         my( $self, $client, $authtoken, $userid, $class, $type ) = @_;
148
149         my( $staff, $user, $evt ) = 
150                 $apputils->checkses_requestor( $authtoken, $userid, 'VIEW_CONTAINER' );
151         return $evt if $evt;
152
153         $logger->debug("User " . $staff->id . 
154                 " retrieving buckets for user $userid [class=$class, type=$type]");
155
156         my $meth = $types{$class} . ".search.atomic";
157         my $buckets;
158
159         if( $type ) {
160                 $buckets = $apputils->simplereq( $svc, 
161                         $meth, { owner => $userid, btype => $type } );
162         } else {
163                 $logger->debug("Grabbing buckets by class $class: $svc : $meth :  {owner => $userid}");
164                 $buckets = $apputils->simplereq( $svc, $meth, { owner => $userid } );
165         }
166
167         return _sort_buckets($buckets);
168 }
169
170 __PACKAGE__->register_method(
171         method  => "bucket_create",
172         api_name        => "open-ils.actor.container.create",
173         notes           => <<"  NOTES");
174                 Creates a new bucket object.  If requestor is different from
175                 bucketOwner, requestor needs CREATE_CONTAINER permissions
176                 PARAMS(authtoken, bucketObject);
177                 Returns the new bucket object
178         NOTES
179
180 sub bucket_create {
181         my( $self, $client, $authtoken, $class, $bucket ) = @_;
182
183         my $e = new_editor(xact=>1, authtoken=>$authtoken);
184         return $e->event unless $e->checkauth;
185
186         if( $bucket->owner ne $e->requestor->id ) {
187                 return $e->event unless
188                         $e->allowed('CREATE_CONTAINER');
189
190         } else {
191                 return $e->event unless
192                         $e->allowed('CREATE_MY_CONTAINER');
193         }
194                 
195         $bucket->clear_id;
196
197     my $evt = OpenILS::Event->new('CONTAINER_EXISTS', 
198         payload => [$class, $bucket->owner, $bucket->btype, $bucket->name]);
199     my $search = {name => $bucket->name, owner => $bucket->owner, btype => $bucket->btype};
200
201         my $obj;
202         if( $class eq 'copy' ) {
203         return $evt if $e->search_container_copy_bucket($search)->[0];
204                 return $e->event unless
205                         $obj = $e->create_container_copy_bucket($bucket);
206         }
207
208         if( $class eq 'callnumber' ) {
209         return $evt if $e->search_container_call_number_bucket($search)->[0];
210                 return $e->event unless
211                         $obj = $e->create_container_call_number_bucket($bucket);
212         }
213
214         if( $class eq 'biblio' ) {
215         return $evt if $e->search_container_biblio_record_entry_bucket($search)->[0];
216                 return $e->event unless
217                         $obj = $e->create_container_biblio_record_entry_bucket($bucket);
218         }
219
220         if( $class eq 'user') {
221         return $evt if $e->search_container_user_bucket($search)->[0];
222                 return $e->event unless
223                         $obj = $e->create_container_user_bucket($bucket);
224         }
225
226         $e->commit;
227         return $obj->id;
228 }
229
230
231 __PACKAGE__->register_method(
232         method  => "bucket_delete",
233         api_name        => "open-ils.actor.container.delete",
234         notes           => <<"  NOTES");
235                 Deletes a bucket object.  If requestor is different from
236                 bucketOwner, requestor needs DELETE_CONTAINER permissions
237                 PARAMS(authtoken, class, bucketId);
238                 Returns the new bucket object
239         NOTES
240
241 # XXX pretty sure no one actually uses this method, 
242 # (see open-ils.actor.container.full_delete) -- should probably deprecate it
243 sub bucket_delete {
244         my( $self, $client, $authtoken, $class, $bucketid ) = @_;
245         my( $bucket, $evt );
246
247         my $e = new_editor(xact=>1, authtoken=>$authtoken);
248         return $e->event unless $e->checkauth;
249
250         ( $bucket, $evt ) = $U->fetch_container_e($e, $bucketid, $class);
251         return $evt if $evt;
252
253         return $e->event unless $e->allowed('DELETE_CONTAINER');
254
255         my $stat;
256         if( $class eq 'copy' ) {
257                 return $e->event unless
258                         $stat = $e->delete_container_copy_bucket($bucket);
259         }
260
261         if( $class eq 'callnumber' ) {
262                 return $e->event unless
263                         $stat = $e->delete_container_call_number_bucket($bucket);
264         }
265
266         if( $class eq 'biblio' ) {
267                 return $e->event unless
268                         $stat = $e->delete_container_biblio_record_entry_bucket($bucket);
269         }
270
271         if( $class eq 'user') {
272                 return $e->event unless
273                         $stat = $e->delete_container_user_bucket($bucket);
274         }
275
276         $e->commit;
277         return $stat;
278
279 }
280
281
282 __PACKAGE__->register_method(
283         method  => "item_create",
284         api_name        => "open-ils.actor.container.item.create",
285         notes           => <<"  NOTES");
286                 PARAMS(authtoken, class, item)
287         NOTES
288
289 sub item_create {
290         my( $self, $client, $authtoken, $class, $item ) = @_;
291
292         my $e = new_editor(xact=>1, authtoken=>$authtoken);
293         return $e->event unless $e->checkauth;
294
295         my ( $bucket, $evt ) = $apputils->fetch_container_e($e, $item->bucket, $class);
296         return $evt if $evt;
297
298         if( $bucket->owner ne $e->requestor->id ) {
299                 return $e->event unless
300                         $e->allowed('CREATE_CONTAINER_ITEM');
301
302         } else {
303                 return $e->event unless
304                         $e->allowed('CREATE_CONTAINER_ITEM'); # new perm here?
305         }
306                 
307         $item->clear_id;
308
309         my $stat;
310         if( $class eq 'copy' ) {
311                 return $e->event unless
312                         $stat = $e->create_container_copy_bucket_item($item);
313         }
314
315         if( $class eq 'callnumber' ) {
316                 return $e->event unless
317                         $stat = $e->create_container_call_number_bucket_item($item);
318         }
319
320         if( $class eq 'biblio' ) {
321                 return $e->event unless
322                         $stat = $e->create_container_biblio_record_entry_bucket_item($item);
323         }
324
325         if( $class eq 'user') {
326                 return $e->event unless
327                         $stat = $e->create_container_user_bucket_item($item);
328         }
329
330         $e->commit;
331         return $stat->id;
332 }
333
334
335
336 __PACKAGE__->register_method(
337         method  => "item_delete",
338         api_name        => "open-ils.actor.container.item.delete",
339         notes           => <<"  NOTES");
340                 PARAMS(authtoken, class, itemId)
341         NOTES
342
343 sub item_delete {
344         my( $self, $client, $authtoken, $class, $itemid ) = @_;
345
346         my $e = new_editor(xact=>1, authtoken=>$authtoken);
347         return $e->event unless $e->checkauth;
348
349         my $ret = __item_delete($e, $class, $itemid);
350         $e->commit unless $U->event_code($ret);
351         return $ret;
352 }
353
354 sub __item_delete {
355         my( $e, $class, $itemid ) = @_;
356         my( $bucket, $item, $evt);
357
358         ( $item, $evt ) = $U->fetch_container_item_e( $e, $itemid, $class );
359         return $evt if $evt;
360
361         ( $bucket, $evt ) = $U->fetch_container_e($e, $item->bucket, $class);
362         return $evt if $evt;
363
364         if( $bucket->owner ne $e->requestor->id ) {
365       my $owner = $e->retrieve_actor_user($bucket->owner)
366          or return $e->die_event;
367                 return $e->event unless $e->allowed('DELETE_CONTAINER_ITEM', $owner->home_ou);
368         }
369
370         my $stat;
371         if( $class eq 'copy' ) {
372                 return $e->event unless
373                         $stat = $e->delete_container_copy_bucket_item($item);
374         }
375
376         if( $class eq 'callnumber' ) {
377                 return $e->event unless
378                         $stat = $e->delete_container_call_number_bucket_item($item);
379         }
380
381         if( $class eq 'biblio' ) {
382                 return $e->event unless
383                         $stat = $e->delete_container_biblio_record_entry_bucket_item($item);
384         }
385
386         if( $class eq 'user') {
387                 return $e->event unless
388                         $stat = $e->delete_container_user_bucket_item($item);
389         }
390
391         return $stat;
392 }
393
394
395 __PACKAGE__->register_method(
396         method  => 'full_delete',
397         api_name        => 'open-ils.actor.container.full_delete',
398         notes           => "Complety removes a container including all attached items",
399 );      
400
401 sub full_delete {
402         my( $self, $client, $authtoken, $class, $containerId ) = @_;
403         my( $container, $evt);
404
405         my $e = new_editor(xact=>1, authtoken=>$authtoken);
406         return $e->event unless $e->checkauth;
407
408         ( $container, $evt ) = $apputils->fetch_container_e($e, $containerId, $class);
409         return $evt if $evt;
410
411         if( $container->owner ne $e->requestor->id ) {
412       my $owner = $e->retrieve_actor_user($container->owner)
413          or return $e->die_event;
414                 return $e->event unless $e->allowed('DELETE_CONTAINER', $owner->home_ou);
415         }
416
417         my $items; 
418
419         my @s = ({bucket => $containerId}, {idlist=>1});
420
421         if( $class eq 'copy' ) {
422                 $items = $e->search_container_copy_bucket_item(@s);
423         }
424
425         if( $class eq 'callnumber' ) {
426                 $items = $e->search_container_call_number_bucket_item(@s);
427         }
428
429         if( $class eq 'biblio' ) {
430                 $items = $e->search_container_biblio_record_entry_bucket_item(@s);
431         }
432
433         if( $class eq 'user') {
434                 $items = $e->search_container_user_bucket_item(@s);
435         }
436
437         __item_delete($e, $class, $_) for @$items;
438
439         my $stat;
440         if( $class eq 'copy' ) {
441                 return $e->event unless
442                         $stat = $e->delete_container_copy_bucket($container);
443         }
444
445         if( $class eq 'callnumber' ) {
446                 return $e->event unless
447                         $stat = $e->delete_container_call_number_bucket($container);
448         }
449
450         if( $class eq 'biblio' ) {
451                 return $e->event unless
452                         $stat = $e->delete_container_biblio_record_entry_bucket($container);
453         }
454
455         if( $class eq 'user') {
456                 return $e->event unless
457                         $stat = $e->delete_container_user_bucket($container);
458         }
459
460         $e->commit;
461         return $stat;
462 }
463
464 __PACKAGE__->register_method(
465         method          => 'container_update',
466         api_name                => 'open-ils.actor.container.update',
467         signature       => q/
468                 Updates the given container item.
469                 @param authtoken The login session key
470                 @param class The container class
471                 @param container The container item
472                 @return true on success, 0 on no update, Event on error
473                 /
474 );
475
476 sub container_update {
477         my( $self, $conn, $authtoken, $class, $container )  = @_;
478
479         my $e = new_editor(xact=>1, authtoken=>$authtoken);
480         return $e->event unless $e->checkauth;
481
482         my ( $dbcontainer, $evt ) = $U->fetch_container_e($e, $container->id, $class);
483         return $evt if $evt;
484
485         if( $e->requestor->id ne $container->owner ) {
486                 return $e->event unless $e->allowed('UPDATE_CONTAINER');
487         }
488
489         my $stat;
490         if( $class eq 'copy' ) {
491                 return $e->event unless
492                         $stat = $e->update_container_copy_bucket($container);
493         }
494
495         if( $class eq 'callnumber' ) {
496                 return $e->event unless
497                         $stat = $e->update_container_call_number_bucket($container);
498         }
499
500         if( $class eq 'biblio' ) {
501                 return $e->event unless
502                         $stat = $e->update_container_biblio_record_entry_bucket($container);
503         }
504
505         if( $class eq 'user') {
506                 return $e->event unless
507                         $stat = $e->update_container_user_bucket($container);
508         }
509
510         $e->commit;
511         return $stat;
512 }
513
514
515
516
517 1;
518
519