Bug 24545: Fix license statements
[koha.git] / C4 / Creators / Batch.pm
1 package C4::Creators::Batch;
2
3 use strict;
4 use warnings;
5
6 use autouse 'Data::Dumper' => qw(Dumper);
7
8 use C4::Context;
9 use C4::Debug;
10
11
12 sub _check_params {
13     my $given_params = {};
14     my $exit_code = 0;
15     my @valid_template_params = (
16         'label_id',
17         'batch_id',
18         'description',
19         'item_number',
20         'card_number',
21         'branch_code',
22         'creator',
23     );
24     if (scalar(@_) >1) {
25         $given_params = {@_};
26         foreach my $key (keys %{$given_params}) {
27             if (!(grep m/$key/, @valid_template_params)) {
28                 warn sprintf('Unrecognized parameter type of "%s".', $key);
29                 $exit_code = 1;
30             }
31         }
32     }
33     else {
34         if (!(grep m/$_/, @valid_template_params)) {
35             warn sprintf('Unrecognized parameter type of %s', $_);
36             $exit_code = 1;
37         }
38     }
39     return $exit_code;
40 }
41
42 sub new {
43     my ($invocant) = shift;
44     my $type = ref($invocant) || $invocant;
45     my $self = {
46         batch_id        => 0,
47         description     => '',
48         items           => [],
49         branch_code     => 'NB',
50         batch_stat      => 0,   # False if any data has changed and the db has not been updated
51         @_,
52     };
53     bless ($self, $type);
54     return $self;
55 }
56
57 sub add_item {
58     my $self = shift;
59     my $number = shift;
60     ref($self) =~ m/C4::(.+)::.+$/;
61     my $number_type = ($1 eq 'Patroncards' ? 'borrower_number' : 'item_number');
62     if ($self->{'batch_id'} == 0){ #if this is a new batch batch_id must be created
63         my $sth = C4::Context->dbh->prepare("SELECT MAX(batch_id) FROM creator_batches;");
64         $sth->execute();
65         my $batch_id = $sth->fetchrow_array;
66         $self->{'batch_id'}= ++$batch_id;
67     }
68     my $query = "INSERT INTO creator_batches (batch_id, description, $number_type, branch_code, creator) VALUES (?,?,?,?,?);";
69     my $sth = C4::Context->dbh->prepare($query);
70 #    $sth->{'TraceLevel'} = 3;
71     $sth->execute($self->{'batch_id'}, $self->{'description'}, $number, $self->{'branch_code'}, $1);
72     if ($sth->err) {
73        warn sprintf('Database returned the following error on attempted INSERT: %s', $sth->errstr);
74         return -1;
75     }
76     $query = "SELECT max(label_id) FROM creator_batches WHERE batch_id=? AND $number_type=? AND branch_code=?;";
77     my $sth1 = C4::Context->dbh->prepare($query);
78     $sth1->execute($self->{'batch_id'}, $number, $self->{'branch_code'});
79     my $label_id = $sth1->fetchrow_array;
80     push (@{$self->{'items'}}, {$number_type => $number, label_id => $label_id});
81     $self->{'batch_stat'} = 1;
82     return 0;
83 }
84
85 sub get_attr {
86     my $self = shift;
87     return $self->{$_[0]};
88 }
89
90 sub remove_item {
91     my $self = shift;
92     my $label_id = shift;
93     my $query = "DELETE FROM creator_batches WHERE label_id=? AND batch_id=?;";
94     my $sth = C4::Context->dbh->prepare($query);
95 #    $sth->{'TraceLevel'} = 3;
96     $sth->execute($label_id, $self->{'batch_id'});
97     if ($sth->err) {
98         warn sprintf('Database returned the following error on attempted DELETE: %s', $sth->errstr);
99         return -1;
100     }
101     @{$self->{'items'}} = grep{$_->{'label_id'} != $label_id} @{$self->{'items'}};
102     $self->{'batch_stat'} = 1;
103     return 0;
104 }
105
106 # FIXME: This method is effectively useless the way the current add_item method is written. Ideally, the items should be added to the object
107 #       and then the save method called. This does not work well in practice due to the inability to pass objects across cgi script calls.
108 #       I'm leaving it here because it should be here and for consistency's sake and once memcached support is fully implemented this should be as well. -cnighswonger
109 #
110 #=head2 $batch->save()
111 #
112 #    Invoking the I<save> method attempts to insert the batch into the database. The method returns
113 #    the new record batch_id upon success and -1 upon failure (This avoids conflicting with a record
114 #    batch_id of 1). Errors are logged to the Apache log.
115 #
116 #    example:
117 #        my $exitstat = $batch->save(); # to save the record behind the $batch object
118 #
119 #=cut
120 #
121 #sub save {
122 #    my $self = shift;
123 #    foreach my $item_number (@{$self->{'items'}}) {
124 #        my $query = "INSERT INTO creator_batches (batch_id, item_number, branch_code) VALUES (?,?,?);";
125 #        my $sth1 = C4::Context->dbh->prepare($query);
126 #        $sth1->execute($self->{'batch_id'}, $item_number->{'item_number'}, $self->{'branch_code'});
127 #        if ($sth1->err) {
128 #            warn sprintf('Database returned the following error on attempted INSERT: %s', $sth1->errstr);
129 #            return -1;
130 #        }
131 #        $self->{'batch_stat'} = 1;
132 #        return $self->{'batch_id'};
133 #    }
134 #}
135
136 sub retrieve {
137     my $invocant = shift;
138     my %opts = @_;
139     my $type = ref($invocant) || $invocant;
140     $type =~ m/C4::(.+)::.+$/;
141     my $number_type = ($1 eq 'Patroncards' ? 'borrower_number' : 'item_number');
142     my $record_flag = 0;
143     my $query = "SELECT * FROM creator_batches WHERE batch_id = ? ORDER BY label_id";
144     my $sth = C4::Context->dbh->prepare($query);
145 #    $sth->{'TraceLevel'} = 3;
146     $sth->execute($opts{'batch_id'});
147     my $self = {
148         batch_id        => $opts{'batch_id'},
149         items           => [],
150     };
151     while (my $record = $sth->fetchrow_hashref) {
152         $self->{'branch_code'} = $record->{'branch_code'};
153         $self->{'creator'} = $record->{'creator'};
154         $self->{'description'} = $record->{'description'};
155         push (@{$self->{'items'}}, {$number_type => $record->{$number_type}, label_id => $record->{'label_id'}});
156         $record_flag = 1;       # true if one or more rows were retrieved
157     }
158     return -2 if $record_flag == 0;     # a hackish sort of way of indicating no such record exists
159     if ($sth->err) {
160         warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
161         return -1;
162     }
163     $self->{'batch_stat'} = 1;
164     bless ($self, $type);
165     return $self;
166 }
167
168 sub delete {
169     my $self = {};
170     my %opts = ();
171     my $call_type = '';
172     my @query_params = ();
173     if (ref($_[0])) {
174         $self = shift;  # check to see if this is a method call
175         $call_type = 'C4::Labels::Batch->delete'; # seems hackish
176         @query_params = ($self->{'batch_id'}, $self->{'branch_code'});
177     }
178     else {
179         shift @_;
180         %opts = @_;
181         $call_type = 'C4::Labels::Batch::delete';
182         @query_params = ($opts{'batch_id'}, $opts{'branch_code'});
183     }
184     if ($query_params[0] eq '') {   # If there is no template id then we cannot delete it
185         warn sprintf('%s : Cannot delete batch as the batch id is invalid or non-existent.', $call_type);
186         return -1;
187     }
188     my $query = "DELETE FROM creator_batches WHERE batch_id = ? AND branch_code =?";
189     my $sth = C4::Context->dbh->prepare($query);
190 #    $sth->{'TraceLevel'} = 3;
191     $sth->execute(@query_params);
192     if ($sth->err) {
193         warn sprintf('%s : Database returned the following error on attempted INSERT: %s', $call_type, $sth->errstr);
194         return -1;
195     }
196     return 0;
197 }
198
199 sub remove_duplicates {
200     my $self = shift;
201     my %seen=();
202     my $query = "DELETE FROM creator_batches WHERE label_id = ?;"; # ORDER BY timestamp ASC LIMIT ?;";
203     my $sth = C4::Context->dbh->prepare($query);
204     my @duplicate_items = grep{
205         $_->{'item_number'}
206             ? $seen{$_->{'item_number'}}++
207             : $seen{$_->{'borrower_number'}}++
208     } @{$self->{'items'}};
209     foreach my $item (@duplicate_items) {
210         $sth->execute($item->{'label_id'});
211         if ($sth->err) {
212             warn sprintf('Database returned the following error on attempted DELETE for label_id %s: %s', $item->{'label_id'}, $sth->errstr);
213             return -1;
214         }
215         $sth->finish(); # Per DBI.pm docs: "If execute() is called on a statement handle that's still active ($sth->{Active} is true) then it should effectively call finish() to tidy up the previous execution results before starting this new execution."
216         @{$self->{'items'}} = grep{$_->{'label_id'} != $item->{'label_id'}} @{$self->{'items'}};  # the correct label/item must be removed from the current batch object as well; this should be done *after* each sql DELETE in case the DELETE fails
217     }
218     return scalar(@duplicate_items);
219 }
220
221 1;
222 __END__
223
224 =head1 NAME
225
226 C4::Labels::Batch - A class for creating and manipulating batch objects in Koha
227
228 =head1 ABSTRACT
229
230 This module provides methods for creating, and otherwise manipulating batch objects used by Koha to create and export labels.
231
232 =head1 METHODS
233
234 =head2 new()
235
236     Invoking the I<new> method constructs a new batch object with no items. It is possible to pre-populate the batch with items and a branch code by passing them
237     as in the second example below.
238
239     B<NOTE:> The items list must be an arrayref pointing to an array of hashes containing a key/data pair after this fashion: {item_number => item_number}. The order of
240     the array elements determines the order of the items in the batch.
241
242     example:
243         C<my $batch = C4::Labels::Batch->new(); # Creates and returns a new batch object>
244
245         C<my $batch = C4::Labels::Batch->new(items => $arrayref, branch_code => branch_code) #    Creates and returns a new batch object containing the items passed in
246             with the branch code passed in.>
247
248     B<NOTE:> This batch is I<not> written to the database until C<$batch->save()> is invoked. You have been warned!
249
250 =head2 $batch->add_item(item_number => $item_number, branch_code => $branch_code)
251
252     Invoking the I<add_item> method will add the supplied item to the batch object.
253
254     example:
255         $batch->add_item(item_number => $item_number, branch_code => $branch_code);
256
257 =head2 $batch->get_attr($attribute)
258
259     Invoking the I<get_attr> method will return the requested attribute.
260
261     example:
262         my @items = $batch->get_attr('items');
263
264 =head2 $batch->remove_item($item_number)
265
266     Invoking the I<remove_item> method will remove the supplied item number from the batch object.
267
268     example:
269         $batch->remove_item($item_number);
270
271 =head2 C4::Labels::Batch->retrieve(batch_id => $batch_id)
272
273     Invoking the I<retrieve> method constructs a new batch object containing the current values for batch_id. The method returns a new object upon success and 1 upon failure.
274     Errors are logged to the Apache log.
275
276     examples:
277
278         my $batch = C4::Labels::Batch->retrieve(batch_id => 1); # Retrieves batch 1 and returns an object containing the record
279
280 =head2 delete()
281
282     Invoking the delete method attempts to delete the template from the database. The method returns -1 upon failure. Errors are logged to the Apache log.
283     NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that batch from the database. See the example below.
284
285     examples:
286         my $exitstat = $batch->delete(); # to delete the record behind the $batch object
287         my $exitstat = C4::Labels::Batch->delete(batch_id => 1); # to delete batch 1
288
289 =head2 remove_duplicates()
290
291     Invoking the remove_duplicates method attempts to remove duplicate items in the batch from the database. The method returns the count of duplicate records removed upon
292     success and -1 upon failure. Errors are logged to the Apache log.
293     NOTE: This method may also be called as a function and passed a key/value pair removing duplicates in the batch passed in. See the example below.
294
295     examples:
296         my $remove_count = $batch->remove_duplicates(); # to remove duplicates the record behind the $batch object
297         my $remove_count = C4::Labels::Batch->remove_duplicates(batch_id => 1); # to remove duplicates in batch 1
298
299 =head1 AUTHOR
300
301 Chris Nighswonger <cnighswonger AT foundations DOT edu>
302
303 =head1 COPYRIGHT
304
305 Copyright 2009 Foundations Bible College.
306
307 =head1 LICENSE
308
309 This file is part of Koha.
310
311 Koha is free software; you can redistribute it and/or modify it
312 under the terms of the GNU General Public License as published by
313 the Free Software Foundation; either version 3 of the License, or
314 (at your option) any later version.
315
316 Koha is distributed in the hope that it will be useful, but
317 WITHOUT ANY WARRANTY; without even the implied warranty of
318 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
319 GNU General Public License for more details.
320
321 You should have received a copy of the GNU General Public License
322 along with Koha; if not, see <http://www.gnu.org/licenses>.
323
324 =head1 DISCLAIMER OF WARRANTY
325
326 Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
327 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
328
329 =cut
330