Bug 14977: Followup to fix issue with NewsChannels.t
[koha.git] / C4 / Creators / Batch.pm
blob4fcf3c4827b3500bbb7c366d30fe0497fda26e49
1 package C4::Creators::Batch;
3 use strict;
4 use warnings;
6 use autouse 'Data::Dumper' => qw(Dumper);
8 use C4::Context;
9 use C4::Debug;
11 BEGIN {
12 use version; our $VERSION = qv('3.07.00.049');
15 sub _check_params {
16 my $given_params = {};
17 my $exit_code = 0;
18 my @valid_template_params = (
19 'label_id',
20 'batch_id',
21 'item_number',
22 'card_number',
23 'branch_code',
24 'creator',
26 if (scalar(@_) >1) {
27 $given_params = {@_};
28 foreach my $key (keys %{$given_params}) {
29 if (!(grep m/$key/, @valid_template_params)) {
30 warn sprintf('Unrecognized parameter type of "%s".', $key);
31 $exit_code = 1;
35 else {
36 if (!(grep m/$_/, @valid_template_params)) {
37 warn sprintf('Unrecognized parameter type of %s', $_);
38 $exit_code = 1;
41 return $exit_code;
44 sub new {
45 my ($invocant) = shift;
46 my $type = ref($invocant) || $invocant;
47 my $self = {
48 batch_id => 0,
49 items => [],
50 branch_code => 'NB',
51 batch_stat => 0, # False if any data has changed and the db has not been updated
52 @_,
54 bless ($self, $type);
55 return $self;
58 sub add_item {
59 my $self = shift;
60 my $number = shift;
61 ref($self) =~ m/C4::(.+)::.+$/;
62 my $number_type = ($1 eq 'Patroncards' ? 'borrower_number' : 'item_number');
63 if ($self->{'batch_id'} == 0){ #if this is a new batch batch_id must be created
64 my $sth = C4::Context->dbh->prepare("SELECT MAX(batch_id) FROM creator_batches;");
65 $sth->execute();
66 my $batch_id = $sth->fetchrow_array;
67 $self->{'batch_id'}= ++$batch_id;
69 my $query = "INSERT INTO creator_batches (batch_id, $number_type, branch_code, creator) VALUES (?,?,?,?);";
70 my $sth = C4::Context->dbh->prepare($query);
71 # $sth->{'TraceLevel'} = 3;
72 $sth->execute($self->{'batch_id'}, $number, $self->{'branch_code'}, $1);
73 if ($sth->err) {
74 warn sprintf('Database returned the following error on attempted INSERT: %s', $sth->errstr);
75 return -1;
77 $query = "SELECT max(label_id) FROM creator_batches WHERE batch_id=? AND $number_type=? AND branch_code=?;";
78 my $sth1 = C4::Context->dbh->prepare($query);
79 $sth1->execute($self->{'batch_id'}, $number, $self->{'branch_code'});
80 my $label_id = $sth1->fetchrow_array;
81 push (@{$self->{'items'}}, {$number_type => $number, label_id => $label_id});
82 $self->{'batch_stat'} = 1;
83 return 0;
86 sub get_attr {
87 my $self = shift;
88 return $self->{$_[0]};
91 sub remove_item {
92 my $self = shift;
93 my $label_id = shift;
94 my $query = "DELETE FROM creator_batches WHERE label_id=? AND batch_id=?;";
95 my $sth = C4::Context->dbh->prepare($query);
96 # $sth->{'TraceLevel'} = 3;
97 $sth->execute($label_id, $self->{'batch_id'});
98 if ($sth->err) {
99 warn sprintf('Database returned the following error on attempted DELETE: %s', $sth->errstr);
100 return -1;
102 @{$self->{'items'}} = grep{$_->{'label_id'} != $label_id} @{$self->{'items'}};
103 $self->{'batch_stat'} = 1;
104 return 0;
107 # FIXME: This method is effectively useless the way the current add_item method is written. Ideally, the items should be added to the object
108 # and then the save method called. This does not work well in practice due to the inability to pass objects across cgi script calls.
109 # 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
111 #=head2 $batch->save()
113 # Invoking the I<save> method attempts to insert the batch into the database. The method returns
114 # the new record batch_id upon success and -1 upon failure (This avoids conflicting with a record
115 # batch_id of 1). Errors are logged to the Apache log.
117 # example:
118 # my $exitstat = $batch->save(); # to save the record behind the $batch object
120 #=cut
122 #sub save {
123 # my $self = shift;
124 # foreach my $item_number (@{$self->{'items'}}) {
125 # my $query = "INSERT INTO creator_batches (batch_id, item_number, branch_code) VALUES (?,?,?);";
126 # my $sth1 = C4::Context->dbh->prepare($query);
127 # $sth1->execute($self->{'batch_id'}, $item_number->{'item_number'}, $self->{'branch_code'});
128 # if ($sth1->err) {
129 # warn sprintf('Database returned the following error on attempted INSERT: %s', $sth1->errstr);
130 # return -1;
132 # $self->{'batch_stat'} = 1;
133 # return $self->{'batch_id'};
137 sub retrieve {
138 my $invocant = shift;
139 my %opts = @_;
140 my $type = ref($invocant) || $invocant;
141 $type =~ m/C4::(.+)::.+$/;
142 my $number_type = ($1 eq 'Patroncards' ? 'borrower_number' : 'item_number');
143 my $record_flag = 0;
144 my $query = "SELECT * FROM creator_batches WHERE batch_id = ? ORDER BY label_id";
145 my $sth = C4::Context->dbh->prepare($query);
146 # $sth->{'TraceLevel'} = 3;
147 $sth->execute($opts{'batch_id'});
148 my $self = {
149 batch_id => $opts{'batch_id'},
150 items => [],
152 while (my $record = $sth->fetchrow_hashref) {
153 $self->{'branch_code'} = $record->{'branch_code'};
154 $self->{'creator'} = $record->{'creator'};
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
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;
163 $self->{'batch_stat'} = 1;
164 bless ($self, $type);
165 return $self;
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'});
178 else {
179 shift @_;
180 %opts = @_;
181 $call_type = 'C4::Labels::Batch::delete';
182 @query_params = ($opts{'batch_id'}, $opts{'branch_code'});
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;
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;
196 return 0;
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;
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
218 return scalar(@duplicate_items);
222 __END__
224 =head1 NAME
226 C4::Labels::Batch - A class for creating and manipulating batch objects in Koha
228 =head1 ABSTRACT
230 This module provides methods for creating, and otherwise manipulating batch objects used by Koha to create and export labels.
232 =head1 METHODS
234 =head2 new()
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.
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.
242 example:
243 C<my $batch = C4::Labels::Batch->new(); # Creates and returns a new batch object>
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.>
248 B<NOTE:> This batch is I<not> written to the database until C<$batch->save()> is invoked. You have been warned!
250 =head2 $batch->add_item(item_number => $item_number, branch_code => $branch_code)
252 Invoking the I<add_item> method will add the supplied item to the batch object.
254 example:
255 $batch->add_item(item_number => $item_number, branch_code => $branch_code);
257 =head2 $batch->get_attr($attribute)
259 Invoking the I<get_attr> method will return the requested attribute.
261 example:
262 my @items = $batch->get_attr('items');
264 =head2 $batch->remove_item($item_number)
266 Invoking the I<remove_item> method will remove the supplied item number from the batch object.
268 example:
269 $batch->remove_item($item_number);
271 =head2 C4::Labels::Batch->retrieve(batch_id => $batch_id)
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.
276 examples:
278 my $batch = C4::Labels::Batch->retrieve(batch_id => 1); # Retrieves batch 1 and returns an object containing the record
280 =head2 delete()
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.
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
289 =head2 remove_duplicates()
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.
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
299 =head1 AUTHOR
301 Chris Nighswonger <cnighswonger AT foundations DOT edu>
303 =head1 COPYRIGHT
305 Copyright 2009 Foundations Bible College.
307 =head1 LICENSE
309 This file is part of Koha.
311 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
312 Foundation; either version 2 of the License, or (at your option) any later version.
314 You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
315 Fifth Floor, Boston, MA 02110-1301 USA.
317 =head1 DISCLAIMER OF WARRANTY
319 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
320 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
322 =cut