26b85d2cd762e8bff7b48a7260a63fff5c0e400e
[working/Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / Application / Circ / NonCat.pm
1 package OpenILS::Application::Circ::NonCat;
2 use base 'OpenILS::Application';
3 use strict; use warnings;
4 use OpenSRF::EX qw(:try);
5 use Data::Dumper;
6 use DateTime;
7 use DateTime::Format::ISO8601;
8 use OpenSRF::Utils qw/:datetime/;
9 use OpenSRF::Utils::Logger qw(:logger);
10 use OpenILS::Application::AppUtils;
11 use OpenILS::Utils::Fieldmapper;
12 use OpenILS::Utils::CStoreEditor qw/:funcs/;
13 $Data::Dumper::Indent = 0;
14
15 my $U = "OpenILS::Application::AppUtils";
16 my $_dt_parser = DateTime::Format::ISO8601->new;
17
18
19 # returns ( $newid, $evt ).  If $evt, then there was an error
20 sub create_non_cat_circ {
21     my( $staffid, $patronid, $circ_lib, $noncat_type, $circ_time, $editor ) = @_;
22
23     my( $id, $nct, $evt );
24     $circ_time ||= 'now';
25     my $circ = Fieldmapper::action::non_cataloged_circulation->new;
26
27     $logger->activity("Creating non-cataloged circulation for ".
28         "staff $staffid, patron $patronid, location $circ_lib, and non-cat type $noncat_type");
29
30     $circ->patron($patronid);
31     $circ->staff($staffid);
32     $circ->circ_lib($circ_lib);
33     $circ->item_type($noncat_type);
34     $circ->circ_time($circ_time);
35
36     if( $editor ) {
37         $evt = $editor->event unless
38             $circ = $editor->create_action_non_cataloged_circulation( $circ )
39
40
41     } else {
42         $id = $U->simplereq(
43             'open-ils.storage',
44             'open-ils.storage.direct.action.non_cataloged_circulation.create', $circ );
45         $evt = $U->DB_UPDATE_FAILED($circ) unless $id;
46         $circ->id($id);
47     }
48
49     if($circ) {
50         my $e = ($editor) ? $editor : new_editor();
51         $circ = noncat_due_date($e, $circ);
52     }
53
54     return( $circ, $evt );
55 }
56
57
58 __PACKAGE__->register_method(
59     method   => "create_noncat_type",
60     api_name => "open-ils.circ.non_cat_type.create",
61     notes    => q/
62         Creates a new non cataloged item type
63         @param authtoken The login session key
64         @param name The name of the new type
65         @param orgId The location where the type will live
66         @return The type object on success and the corresponding
67         event on failure
68     /
69 );
70
71 sub create_noncat_type {
72     my( $self, $client, $authtoken, $name, $orgId, $interval, $inhouse ) = @_;
73
74     my $e = new_editor(authtoken=>$authtoken, xact=>1);
75     return $e->die_event unless $e->checkauth;
76     return $e->die_event unless $e->allowed('CREATE_NON_CAT_TYPE', $orgId);
77
78     # grab all of "my" non-cat types and see if one with 
79     # the requested name already exists
80     my $types = retrieve_noncat_types_all($self, $client, $orgId);
81     for(@$types) {
82         if( $_->name eq $name ) {
83             $e->rollback;
84             return OpenILS::Event->new('NON_CAT_TYPE_EXISTS', payload => $name);
85         }
86     }
87
88     my $type = Fieldmapper::config::non_cataloged_type->new;
89     $type->name($name);
90     $type->owning_lib($orgId);
91     $type->circ_duration($interval);
92     $type->in_house( ($inhouse) ? 't' : 'f' );
93
94     $e->create_config_non_cataloged_type($type) or return $e->die_event;
95     $e->commit;
96     return $type;
97 }
98
99
100 __PACKAGE__->register_method(
101     method   => "update_noncat_type",
102     api_name => "open-ils.circ.non_cat_type.update",
103     notes    => q/
104         Updates a non-cataloged type object
105         @param authtoken The login session key
106         @param type The updated type object
107         @return The result of the DB update call unless a preceeding event occurs, 
108             in which case the event will be returned
109     /
110 );
111
112 sub update_noncat_type {
113     my( $self, $client, $authtoken, $type ) = @_;
114     my $e = new_editor(xact=>1, authtoken=>$authtoken);
115     return $e->die_event unless $e->checkauth;
116
117     my $otype = $e->retrieve_config_non_cataloged_type($type->id) 
118         or return $e->die_event;
119
120     return $e->die_event unless 
121         $e->allowed('UPDATE_NON_CAT_TYPE', $otype->owning_lib);
122
123     $type->owning_lib($otype->owning_lib); # do not allow them to "move" the object
124
125     $e->update_config_non_cataloged_type($type) or return $e->die_event;
126     $e->commit;
127     return 1;
128 }
129
130 __PACKAGE__->register_method(
131     method    => "retrieve_noncat_types_all",
132     api_name  => "open-ils.circ.non_cat_types.retrieve.all",
133     signature => {
134         desc   => 'Retrieves the non-cat types at the requested location as well '
135                 . 'as those above and below it in the org tree',
136         params => [
137             { name => 'orgId', desc => 'Org unit ID of the base location',   type => 'number' },
138             { name => 'depth', desc => 'Depth limit of the tree (optional)', type => 'number' }
139         ],
140         return => {
141             desc => 'Array of non-cat objects, event on error'
142         },
143     }
144 );
145
146 sub retrieve_noncat_types_all {
147     my( $self, $client, $orgId, $depth ) = @_;
148     my $meth = 'open-ils.storage.ranged.config.non_cataloged_type.retrieve.atomic';
149     my $svc  = 'open-ils.storage';
150     return $U->simplereq($svc, $meth, $orgId, $depth) if defined($depth);
151     return $U->simplereq($svc, $meth, $orgId);
152 }
153
154
155 __PACKAGE__->register_method(
156     method    => 'fetch_noncat',
157     api_name  => 'open-ils.circ.non_cataloged_circulation.retrieve',
158     signature => {
159         desc   => 'Retrieve a circulation on a non cataloged item for a given Circ ID.  If the operator is not the '
160                 . 'patron owner of the circ, the VIEW_CIRCULATIONS permission is required',
161         params => [
162             { desc => 'Authentication token', type => 'string' },
163             { desc => 'Circulation ID',       type => 'number' }
164         ],
165         return => {
166             desc => 'Circulation object, event on error',
167         },
168     }
169 );
170
171 sub fetch_noncat {
172     my( $self, $conn, $auth, $circid ) = @_;
173     my $e = new_editor( authtoken => $auth );
174     return $e->event unless $e->checkauth;
175     my $c = $e->retrieve_action_non_cataloged_circulation($circid)
176         or return $e->event;
177     if( $c->patron ne $e->requestor->id ) {
178         return $e->event unless $e->allowed('VIEW_CIRCULATIONS'); # XXX rely on editor perm
179     }
180     return noncat_due_date($e, $c);
181 }
182
183 sub noncat_due_date {
184     my($e, $circ) = @_;
185
186     my $otype = $e->retrieve_config_non_cataloged_type($circ->item_type) 
187         or return $e->die_event;
188
189     my $duedate = $_dt_parser->parse_datetime( cleanse_ISO8601($circ->circ_time) );
190     $duedate = $duedate
191         ->add( seconds => interval_to_seconds($otype->circ_duration) )
192         ->strftime('%FT%T%z');
193
194     my $offset = $U->storagereq(
195         'open-ils.storage.actor.org_unit.closed_date.overlap',
196         $circ->circ_lib,
197         $duedate
198     );
199
200     $duedate = $offset->{end} if ($offset);
201     $circ->duedate($duedate);
202
203     return $circ;
204 }
205
206
207
208 __PACKAGE__->register_method(
209     method        => 'fetch_open_noncats',
210     authoritative => 1,
211     api_name      => 'open-ils.circ.open_non_cataloged_circulation.user',
212     signature     => {
213         desca   => 'For a given user, returns an id-list of non-cataloged circulations that are considered open as of now.  ' .
214                    'A circ is open if circ time + circ duration (based on type) is > than now.  If trying to view the circs ' .
215                    'of another user, the VIEW_CIRCULATIONS permission is required',
216         params => [
217             { desc => 'Authentication token',                            type => 'string' },
218             { desc => 'UserID (optional: defaults to the session user)', type => 'number' }
219         ],
220         return => {
221             desc => 'Array of non-cataloged circ IDs, event on error'
222         },
223     }
224 );
225
226 sub fetch_open_noncats {
227     my( $self, $conn, $auth, $userid ) = @_;
228     my $e = new_editor( authtoken => $auth );
229     return $e->event unless $e->checkauth;
230     $userid ||= $e->requestor->id;
231     if( $e->requestor->id ne $userid ) {
232         return $e->event unless $e->allowed('VIEW_CIRCULATIONS'); # XXX rely on editor perm
233     }
234
235     return $U->simplereq(
236         'open-ils.storage',
237         'open-ils.storage.action.open_non_cataloged_circulation.user',
238         $userid
239     );
240 }
241
242
243 __PACKAGE__->register_method(
244     method   => 'delete_noncat',
245     api_name => 'open-ils.circ.non_cataloged_type.delete',
246 );
247 sub delete_noncat {
248     my( $self, $conn, $auth, $typeid ) = @_;
249     my $e = new_editor(xact=>1, authtoken => $auth);
250     return $e->die_event unless $e->checkauth;
251
252     my $nc = $e->retrieve_config_non_cataloged_type($typeid)
253         or return $e->die_event;
254
255     $e->allowed('DELETE_NON_CAT_TYPE', $nc->owning_lib) # XXX rely on editor perm
256         or return $e->die_event;
257
258     #   XXX Add checks to see if this type is in use by a transaction
259
260     $e->delete_config_non_cataloged_type($nc) or return $e->die_event;
261     $e->commit;
262     return 1;
263 }
264
265
266 1;