Bug 15066: Make transfer rotating collection works under Plack
[koha.git] / C4 / RotatingCollections.pm
1 package C4::RotatingCollections;
2
3 # $Id: RotatingCollections.pm,v 0.1 2007/04/20 kylemhall
4
5 # This package is inteded to keep track of what library
6 # Items of a certain collection should be at.
7
8 # Copyright 2007 Kyle Hall
9 #
10 # This file is part of Koha.
11 #
12 # Koha is free software; you can redistribute it and/or modify it
13 # under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 3 of the License, or
15 # (at your option) any later version.
16 #
17 # Koha is distributed in the hope that it will be useful, but
18 # WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with Koha; if not, see <http://www.gnu.org/licenses>.
24
25 use Modern::Perl;
26
27 use C4::Context;
28 use C4::Circulation;
29 use C4::Reserves qw(CheckReserves);
30 use Koha::Database;
31
32 use DBI;
33
34 use Data::Dumper;
35
36 use vars qw($VERSION @ISA @EXPORT);
37
38 # set the version for version checking
39 $VERSION = 3.07.00.049;
40
41 =head1 NAME
42
43 C4::RotatingCollections - Functions for managing rotating collections
44
45 =head1 FUNCTIONS
46
47 =cut
48
49 BEGIN {
50     require Exporter;
51     @ISA    = qw( Exporter );
52     @EXPORT = qw(
53       CreateCollection
54       UpdateCollection
55       DeleteCollection
56
57       GetItemsInCollection
58
59       GetCollection
60       GetCollections
61
62       AddItemToCollection
63       RemoveItemFromCollection
64       TransferCollection
65
66       GetCollectionItemBranches
67     );
68 }
69
70 =head2  CreateCollection
71  ( $success, $errorcode, $errormessage ) = CreateCollection( $title, $description );
72  Creates a new collection
73
74  Input:
75    $title: short description of the club or service
76    $description: long description of the club or service
77
78  Output:
79    $success: 1 if all database operations were successful, 0 otherwise
80    $errorCode: Code for reason of failure, good for translating errors in templates
81    $errorMessage: English description of error
82
83 =cut
84
85 sub CreateCollection {
86     my ( $title, $description ) = @_;
87
88     my $schema = Koha::Database->new()->schema();
89     my $duplicate_titles = $schema->resultset('Collection')->count({ colTitle => $title });
90
91     ## Check for all necessary parameters
92     if ( !$title ) {
93         return ( 0, 1, "NO_TITLE" );
94     } elsif ( $duplicate_titles ) {
95         return ( 0, 2, "DUPLICATE_TITLE" );
96     }
97
98     $description ||= q{};
99
100     my $success = 1;
101
102     my $dbh = C4::Context->dbh;
103
104     my $sth;
105     $sth = $dbh->prepare(
106         "INSERT INTO collections ( colId, colTitle, colDesc )
107                         VALUES ( NULL, ?, ? )"
108     );
109     $sth->execute( $title, $description ) or return ( 0, 3, $sth->errstr() );
110
111     return 1;
112
113 }
114
115 =head2 UpdateCollection
116
117  ( $success, $errorcode, $errormessage ) = UpdateCollection( $colId, $title, $description );
118
119 Updates a collection
120
121  Input:
122    $colId: id of the collection to be updated
123    $title: short description of the club or service
124    $description: long description of the club or service
125
126  Output:
127    $success: 1 if all database operations were successful, 0 otherwise
128    $errorCode: Code for reason of failure, good for translating errors in templates
129    $errorMessage: English description of error
130
131 =cut
132
133 sub UpdateCollection {
134     my ( $colId, $title, $description ) = @_;
135
136     my $schema = Koha::Database->new()->schema();
137     my $duplicate_titles = $schema->resultset('Collection')->count({ colTitle => $title,  -not => { colId => $colId } });
138
139     ## Check for all necessary parameters
140     if ( !$colId ) {
141         return ( 0, 1, "NO_ID" );
142     }
143     if ( !$title ) {
144         return ( 0, 2, "NO_TITLE" );
145     }
146     if ( $duplicate_titles ) {
147         return ( 0, 3, "DUPLICATE_TITLE" );
148     }
149
150     my $dbh = C4::Context->dbh;
151
152     $description ||= q{};
153
154     my $sth;
155     $sth = $dbh->prepare(
156         "UPDATE collections
157                         SET 
158                         colTitle = ?, colDesc = ? 
159                         WHERE colId = ?"
160     );
161     $sth->execute( $title, $description, $colId )
162       or return ( 0, 4, $sth->errstr() );
163
164     return 1;
165
166 }
167
168 =head2 DeleteCollection
169
170  ( $success, $errorcode, $errormessage ) = DeleteCollection( $colId );
171  Deletes a collection of the given id
172
173  Input:
174    $colId : id of the Archetype to be deleted
175
176  Output:
177    $success: 1 if all database operations were successful, 0 otherwise
178    $errorCode: Code for reason of failure, good for translating errors in templates
179    $errorMessage: English description of error
180
181 =cut
182
183 sub DeleteCollection {
184     my ($colId) = @_;
185
186     ## Parameter check
187     if ( !$colId ) {
188         return ( 0, 1, "NO_ID" );
189     }
190
191     my $dbh = C4::Context->dbh;
192
193     my $sth;
194
195     $sth = $dbh->prepare("DELETE FROM collections WHERE colId = ?");
196     $sth->execute($colId) or return ( 0, 4, $sth->errstr() );
197
198     return 1;
199 }
200
201 =head2 GetCollections
202
203  $collections = GetCollections();
204  Returns data about all collections
205
206  Output:
207   On Success:
208    $results: Reference to an array of associated arrays
209   On Failure:
210    $errorCode: Code for reason of failure, good for translating errors in templates
211    $errorMessage: English description of error
212
213 =cut
214
215 sub GetCollections {
216
217     my $dbh = C4::Context->dbh;
218
219     my $sth = $dbh->prepare("SELECT * FROM collections");
220     $sth->execute() or return ( 1, $sth->errstr() );
221
222     my @results;
223     while ( my $row = $sth->fetchrow_hashref ) {
224         push( @results, $row );
225     }
226
227     return \@results;
228 }
229
230 =head2 GetItemsInCollection
231
232  ( $results, $success, $errorcode, $errormessage ) = GetItemsInCollection( $colId );
233
234  Returns information about the items in the given collection
235  
236  Input:
237    $colId: The id of the collection
238
239  Output:
240    $results: Reference to an array of associated arrays
241    $success: 1 if all database operations were successful, 0 otherwise
242    $errorCode: Code for reason of failure, good for translating errors in templates
243    $errorMessage: English description of error
244
245 =cut
246
247 sub GetItemsInCollection {
248     my ($colId) = @_;
249
250     ## Parameter check
251     if ( !$colId ) {
252         return ( 0, 0, 1, "NO_ID" );
253     }
254
255     my $dbh = C4::Context->dbh;
256
257     my $sth = $dbh->prepare(
258         "SELECT
259                              biblio.title,
260                              biblio.biblionumber,
261                              items.itemcallnumber,
262                              items.barcode
263                            FROM collections, collections_tracking, items, biblio
264                            WHERE collections.colId = collections_tracking.colId
265                            AND collections_tracking.itemnumber = items.itemnumber
266                            AND items.biblionumber = biblio.biblionumber
267                            AND collections.colId = ? ORDER BY biblio.title"
268     );
269     $sth->execute($colId) or return ( 0, 0, 2, $sth->errstr() );
270
271     my @results;
272     while ( my $row = $sth->fetchrow_hashref ) {
273         push( @results, $row );
274     }
275
276     return \@results;
277 }
278
279 =head2 GetCollection
280
281  ( $colId, $colTitle, $colDesc, $colBranchcode ) = GetCollection( $colId );
282
283 Returns information about a collection
284
285  Input:
286    $colId: Id of the collection
287  Output:
288    $colId, $colTitle, $colDesc, $colBranchcode
289
290 =cut
291
292 sub GetCollection {
293     my ($colId) = @_;
294
295     my $dbh = C4::Context->dbh;
296
297     my ( $sth, @results );
298     $sth = $dbh->prepare("SELECT * FROM collections WHERE colId = ?");
299     $sth->execute($colId) or return 0;
300
301     my $row = $sth->fetchrow_hashref;
302
303     return (
304         $$row{'colId'},   $$row{'colTitle'},
305         $$row{'colDesc'}, $$row{'colBranchcode'}
306     );
307
308 }
309
310 =head2 AddItemToCollection
311
312  ( $success, $errorcode, $errormessage ) = AddItemToCollection( $colId, $itemnumber );
313
314 Adds an item to a rotating collection.
315
316  Input:
317    $colId: Collection to add the item to.
318    $itemnumber: Item to be added to the collection
319  Output:
320    $success: 1 if all database operations were successful, 0 otherwise
321    $errorCode: Code for reason of failure, good for translating errors in templates
322    $errorMessage: English description of error
323
324 =cut
325
326 sub AddItemToCollection {
327     my ( $colId, $itemnumber ) = @_;
328
329     ## Check for all necessary parameters
330     if ( !$colId ) {
331         return ( 0, 1, "NO_ID" );
332     }
333     if ( !$itemnumber ) {
334         return ( 0, 2, "NO_ITEM" );
335     }
336
337     if ( isItemInThisCollection( $itemnumber, $colId ) ) {
338         return ( 0, 2, "IN_COLLECTION" );
339     }
340     elsif ( isItemInAnyCollection($itemnumber) ) {
341         return ( 0, 3, "IN_COLLECTION_OTHER" );
342     }
343
344     my $dbh = C4::Context->dbh;
345
346     my $sth;
347     $sth = $dbh->prepare("
348         INSERT INTO collections_tracking (
349             colId,
350             itemnumber
351         ) VALUES ( ?, ? )
352     ");
353     $sth->execute( $colId, $itemnumber ) or return ( 0, 3, $sth->errstr() );
354
355     return 1;
356
357 }
358
359 =head2  RemoveItemFromCollection
360
361  ( $success, $errorcode, $errormessage ) = RemoveItemFromCollection( $colId, $itemnumber );
362
363 Removes an item to a collection
364
365  Input:
366    $colId: Collection to add the item to.
367    $itemnumber: Item to be removed from collection
368
369  Output:
370    $success: 1 if all database operations were successful, 0 otherwise
371    $errorCode: Code for reason of failure, good for translating errors in templates
372    $errorMessage: English description of error
373
374 =cut
375
376 sub RemoveItemFromCollection {
377     my ( $colId, $itemnumber ) = @_;
378
379     ## Check for all necessary parameters
380     if ( !$itemnumber ) {
381         return ( 0, 2, "NO_ITEM" );
382     }
383
384     if ( !isItemInThisCollection( $itemnumber, $colId ) ) {
385         return ( 0, 2, "NOT_IN_COLLECTION" );
386     }
387
388     my $dbh = C4::Context->dbh;
389
390     my $sth;
391     $sth = $dbh->prepare(
392         "DELETE FROM collections_tracking
393                         WHERE itemnumber = ?"
394     );
395     $sth->execute($itemnumber) or return ( 0, 3, $sth->errstr() );
396
397     return 1;
398 }
399
400 =head2 TransferCollection
401
402  ( $success, $errorcode, $errormessage ) = TransferCollection( $colId, $colBranchcode );
403
404 Transfers a collection to another branch
405
406  Input:
407    $colId: id of the collection to be updated
408    $colBranchcode: branch where collection is moving to
409
410  Output:
411    $success: 1 if all database operations were successful, 0 otherwise
412    $errorCode: Code for reason of failure, good for translating errors in templates
413    $errorMessage: English description of error
414
415 =cut
416
417 sub TransferCollection {
418     my ( $colId, $colBranchcode ) = @_;
419
420     ## Check for all necessary parameters
421     if ( !$colId ) {
422         return ( 0, 1, "NO_ID" );
423     }
424     if ( !$colBranchcode ) {
425         return ( 0, 2, "NO_BRANCHCODE" );
426     }
427
428     my $dbh = C4::Context->dbh;
429
430     my $sth;
431     $sth = $dbh->prepare(
432         "UPDATE collections
433                         SET 
434                         colBranchcode = ? 
435                         WHERE colId = ?"
436     );
437     $sth->execute( $colBranchcode, $colId ) or return ( 0, 4, $sth->errstr() );
438
439     $sth = $dbh->prepare(q{
440         SELECT items.itemnumber, items.barcode FROM collections_tracking
441         LEFT JOIN items ON collections_tracking.itemnumber = items.itemnumber
442         LEFT JOIN issues ON items.itemnumber = issues.itemnumber
443         WHERE issues.borrowernumber IS NULL
444           AND collections_tracking.colId = ?
445     });
446     $sth->execute($colId) or return ( 0, 4, $sth->errstr );
447     my @results;
448     while ( my $item = $sth->fetchrow_hashref ) {
449         my ($status) = CheckReserves( $item->{itemnumber} );
450         my @transfers = C4::Circulation::GetTransfers( $item->{itemnumber} );
451         C4::Circulation::transferbook( $colBranchcode, $item->{barcode}, my $ignore_reserves = 1 ) unless ( $status eq 'Waiting' || @transfers );
452     }
453
454     return 1;
455
456 }
457
458 =head2 GetCollectionItemBranches
459
460   my ( $holdingBranch, $collectionBranch ) = GetCollectionItemBranches( $itemnumber );
461
462 =cut
463
464 sub GetCollectionItemBranches {
465     my ($itemnumber) = @_;
466
467     if ( !$itemnumber ) {
468         return;
469     }
470
471     my $dbh = C4::Context->dbh;
472
473     my ( $sth, @results );
474     $sth = $dbh->prepare(
475 "SELECT holdingbranch, colBranchcode FROM items, collections, collections_tracking
476                         WHERE items.itemnumber = collections_tracking.itemnumber
477                         AND collections.colId = collections_tracking.colId
478                         AND items.itemnumber = ?"
479     );
480     $sth->execute($itemnumber);
481
482     my $row = $sth->fetchrow_hashref;
483
484     return ( $$row{'holdingbranch'}, $$row{'colBranchcode'}, );
485 }
486
487 =head2 isItemInThisCollection
488
489   $inCollection = isItemInThisCollection( $itemnumber, $colId );
490
491 =cut
492
493 sub isItemInThisCollection {
494     my ( $itemnumber, $colId ) = @_;
495
496     my $dbh = C4::Context->dbh;
497
498     my $sth = $dbh->prepare(
499 "SELECT COUNT(*) as inCollection FROM collections_tracking WHERE itemnumber = ? AND colId = ?"
500     );
501     $sth->execute( $itemnumber, $colId ) or return (0);
502
503     my $row = $sth->fetchrow_hashref;
504
505     return $$row{'inCollection'};
506 }
507
508 =head2 isItemInAnyCollection
509
510 $inCollection = isItemInAnyCollection( $itemnumber );
511
512 =cut
513
514 sub isItemInAnyCollection {
515     my ($itemnumber) = @_;
516
517     my $dbh = C4::Context->dbh;
518
519     my $sth = $dbh->prepare(
520         "SELECT itemnumber FROM collections_tracking WHERE itemnumber = ?");
521     $sth->execute($itemnumber) or return (0);
522
523     my $row = $sth->fetchrow_hashref;
524
525     $itemnumber = $row->{itemnumber};
526     if ($itemnumber) {
527         return 1;
528     }
529     else {
530         return 0;
531     }
532 }
533
534 1;
535
536 __END__
537
538 =head1 AUTHOR
539
540 Kyle Hall <kylemhall@gmail.com>
541
542 =cut