Bug 16573: change created_on type - atomic update
[koha.git] / C4 / Members / AttributeTypes.pm
blobd4927dbec22f6e021704da0de49bf6717fdb5f88
1 package C4::Members::AttributeTypes;
3 # Copyright (C) 2008 LibLime
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use strict;
21 #use warnings; FIXME - Bug 2505
22 use C4::Context;
26 =head1 NAME
28 C4::Members::AttributeTypes - mananage extended patron attribute types
30 =head1 SYNOPSIS
32 my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes();
34 my $attr_type = C4::Members::AttributeTypes->new($code, $description);
35 $attr_type->code($code);
36 $attr_type->description($description);
37 $attr_type->repeatable($repeatable);
38 $attr_type->unique_id($unique_id);
39 $attr_type->opac_display($opac_display);
40 $attr_type->staff_searchable($staff_searchable);
41 $attr_type->authorised_value_category($authorised_value_category);
42 $attr_type->store();
43 $attr_type->delete();
45 my $attr_type = C4::Members::AttributeTypes->fetch($code);
46 $attr_type = C4::Members::AttributeTypes->delete($code);
48 =head1 FUNCTIONS
50 =head2 GetAttributeTypes
52 my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes($all_fields);
54 Returns an array of hashrefs of each attribute type defined
55 in the database. The array is sorted by code. Each hashref contains
56 at least the following fields:
58 - code
59 - description
61 If $all_fields is true, then each hashref also contains the other fields from borrower_attribute_types.
63 =cut
65 sub GetAttributeTypes {
66 my $all = @_ ? shift : 0;
67 my $no_branch_limit = @_ ? shift : 0;
68 my $branch_limit = $no_branch_limit
69 ? 0
70 : C4::Context->userenv ? C4::Context->userenv->{"branch"} : 0;
71 my $select = $all ? '*' : 'DISTINCT(code), description, class';
73 my $dbh = C4::Context->dbh;
74 my $query = "SELECT $select FROM borrower_attribute_types";
75 $query .= qq{
76 LEFT JOIN borrower_attribute_types_branches ON bat_code = code
77 WHERE b_branchcode = ? OR b_branchcode IS NULL
78 } if $branch_limit;
79 $query .= " ORDER BY code";
80 my $sth = $dbh->prepare($query);
81 $sth->execute( $branch_limit ? $branch_limit : () );
82 my $results = $sth->fetchall_arrayref({});
83 $sth->finish;
84 return @$results;
87 sub GetAttributeTypes_hashref {
88 my %hash = map {$_->{code} => $_} GetAttributeTypes(@_);
89 return \%hash;
92 =head2 AttributeTypeExists
94 my $have_attr_xyz = C4::Members::AttributeTypes::AttributeTypeExists($code)
96 Returns true if we have attribute type C<$code>
97 in the database.
99 =cut
101 sub AttributeTypeExists {
102 my ($code) = @_;
103 my $dbh = C4::Context->dbh;
104 my $exists = $dbh->selectrow_array("SELECT code FROM borrower_attribute_types WHERE code = ?", undef, $code);
105 return $exists;
108 =head1 METHODS
110 my $attr_type = C4::Members::AttributeTypes->new($code, $description);
112 Create a new attribute type.
114 =cut
116 sub new {
117 my $class = shift;
118 my $self = {};
120 $self->{'code'} = shift;
121 $self->{'description'} = shift;
122 $self->{'repeatable'} = 0;
123 $self->{'unique_id'} = 0;
124 $self->{'opac_display'} = 0;
125 $self->{'staff_searchable'} = 0;
126 $self->{'display_checkout'} = 0;
127 $self->{'authorised_value_category'} = '';
128 $self->{'category_code'} = '';
129 $self->{'category_description'} = '';
130 $self->{'class'} = '';
132 bless $self, $class;
133 return $self;
136 =head2 fetch
138 my $attr_type = C4::Members::AttributeTypes->fetch($code);
140 Fetches an attribute type from the database. If no
141 type with the given C<$code> exists, returns undef.
143 =cut
145 sub fetch {
146 my $class = shift;
147 my $code = shift;
148 my $self = {};
149 my $dbh = C4::Context->dbh();
151 my $sth = $dbh->prepare_cached("
152 SELECT borrower_attribute_types.*, categories.description AS category_description
153 FROM borrower_attribute_types
154 LEFT JOIN categories ON borrower_attribute_types.category_code=categories.categorycode
155 WHERE code =?");
156 $sth->execute($code);
157 my $row = $sth->fetchrow_hashref;
158 $sth->finish();
159 return unless defined $row;
161 $self->{'code'} = $row->{'code'};
162 $self->{'description'} = $row->{'description'};
163 $self->{'repeatable'} = $row->{'repeatable'};
164 $self->{'unique_id'} = $row->{'unique_id'};
165 $self->{'opac_display'} = $row->{'opac_display'};
166 $self->{'staff_searchable'} = $row->{'staff_searchable'};
167 $self->{'display_checkout'} = $row->{'display_checkout'};
168 $self->{'authorised_value_category'} = $row->{'authorised_value_category'};
169 $self->{'category_code'} = $row->{'category_code'};
170 $self->{'category_description'} = $row->{'category_description'};
171 $self->{'class'} = $row->{'class'};
173 $sth = $dbh->prepare("SELECT branchcode, branchname FROM borrower_attribute_types_branches, branches WHERE b_branchcode = branchcode AND bat_code = ?;");
174 $sth->execute( $code );
175 while ( my $data = $sth->fetchrow_hashref ) {
176 push @{ $self->{branches} }, $data;
178 $sth->finish();
180 bless $self, $class;
181 return $self;
184 =head2 store
186 $attr_type->store();
188 Stores attribute type in the database. If the type
189 previously retrieved from the database via the fetch()
190 method, the DB representation of the type is replaced.
192 =cut
194 sub store {
195 my $self = shift;
197 my $dbh = C4::Context->dbh;
198 my $sth;
199 my $existing = __PACKAGE__->fetch($self->{'code'});
200 if (defined $existing) {
201 $sth = $dbh->prepare_cached("UPDATE borrower_attribute_types
202 SET description = ?,
203 repeatable = ?,
204 unique_id = ?,
205 opac_display = ?,
206 staff_searchable = ?,
207 authorised_value_category = ?,
208 display_checkout = ?,
209 category_code = ?,
210 class = ?
211 WHERE code = ?");
212 } else {
213 $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types
214 (description, repeatable, unique_id, opac_display,
215 staff_searchable, authorised_value_category, display_checkout, category_code, class, code)
216 VALUES (?, ?, ?, ?,
217 ?, ?, ?, ?, ?, ?)");
219 $sth->execute(
220 $self->{description},
221 $self->{repeatable},
222 $self->{unique_id},
223 $self->{opac_display},
224 $self->{staff_searchable},
225 $self->{authorised_value_category},
226 $self->{display_checkout},
227 $self->{category_code} || undef,
228 $self->{class},
229 $self->{code},
232 if ( defined $$self{branches} ) {
233 $sth = $dbh->prepare("DELETE FROM borrower_attribute_types_branches WHERE bat_code = ?");
234 $sth->execute( $$self{code} );
235 $sth = $dbh->prepare(
236 "INSERT INTO borrower_attribute_types_branches
237 ( bat_code, b_branchcode )
238 VALUES ( ?, ? )"
240 for my $branchcode ( @{$$self{branches}} ) {
241 next if not $branchcode;
242 $sth->bind_param( 1, $$self{code} );
243 $sth->bind_param( 2, $branchcode );
244 $sth->execute;
247 $sth->finish;
250 =head2 code
252 my $code = $attr_type->code();
253 $attr_type->code($code);
255 Accessor. Note that the code is immutable once
256 a type is created or fetched from the database.
258 =cut
260 sub code {
261 my $self = shift;
262 return $self->{'code'};
265 =head2 description
267 my $description = $attr_type->description();
268 $attr_type->description($description);
270 Accessor.
272 =cut
274 sub description {
275 my $self = shift;
276 @_ ? $self->{'description'} = shift : $self->{'description'};
279 =head2 branches
281 my $branches = $attr_type->branches();
282 $attr_type->branches($branches);
284 Accessor.
286 =cut
288 sub branches {
289 my $self = shift;
290 @_ ? $self->{branches} = shift : $self->{branches};
293 =head2 repeatable
295 my $repeatable = $attr_type->repeatable();
296 $attr_type->repeatable($repeatable);
298 Accessor. The C<$repeatable> argument
299 is interpreted as a Perl boolean.
301 =cut
303 sub repeatable {
304 my $self = shift;
305 @_ ? $self->{'repeatable'} = ((shift) ? 1 : 0) : $self->{'repeatable'};
308 =head2 unique_id
310 my $unique_id = $attr_type->unique_id();
311 $attr_type->unique_id($unique_id);
313 Accessor. The C<$unique_id> argument
314 is interpreted as a Perl boolean.
316 =cut
318 sub unique_id {
319 my $self = shift;
320 @_ ? $self->{'unique_id'} = ((shift) ? 1 : 0) : $self->{'unique_id'};
323 =head2 opac_display
325 my $opac_display = $attr_type->opac_display();
326 $attr_type->opac_display($opac_display);
328 Accessor. The C<$opac_display> argument
329 is interpreted as a Perl boolean.
331 =cut
333 sub opac_display {
334 my $self = shift;
335 @_ ? $self->{'opac_display'} = ((shift) ? 1 : 0) : $self->{'opac_display'};
338 =head2 staff_searchable
340 my $staff_searchable = $attr_type->staff_searchable();
341 $attr_type->staff_searchable($staff_searchable);
343 Accessor. The C<$staff_searchable> argument
344 is interpreted as a Perl boolean.
346 =cut
348 sub staff_searchable {
349 my $self = shift;
350 @_ ? $self->{'staff_searchable'} = ((shift) ? 1 : 0) : $self->{'staff_searchable'};
353 =head2 display_checkout
355 my $display_checkout = $attr_type->display_checkout();
356 $attr_type->display_checkout($display_checkout);
358 Accessor. The C<$display_checkout> argument
359 is interpreted as a Perl boolean.
361 =cut
363 sub display_checkout {
364 my $self = shift;
365 @_ ? $self->{'display_checkout'} = ((shift) ? 1 : 0) : $self->{'display_checkout'};
368 =head2 authorised_value_category
370 my $authorised_value_category = $attr_type->authorised_value_category();
371 $attr_type->authorised_value_category($authorised_value_category);
373 Accessor.
375 =cut
377 sub authorised_value_category {
378 my $self = shift;
379 @_ ? $self->{'authorised_value_category'} = shift : $self->{'authorised_value_category'};
382 =head2 category_code
384 my $category_code = $attr_type->category_code();
385 $attr_type->category_code($category_code);
387 Accessor.
389 =cut
391 sub category_code {
392 my $self = shift;
393 @_ ? $self->{'category_code'} = shift : $self->{'category_code'};
396 =head2 category_description
398 my $category_description = $attr_type->category_description();
399 $attr_type->category_description($category_description);
401 Accessor.
403 =cut
405 sub category_description {
406 my $self = shift;
407 @_ ? $self->{'category_description'} = shift : $self->{'category_description'};
410 =head2 class
412 my $class = $attr_type->class();
413 $attr_type->class($class);
415 Accessor.
417 =cut
419 sub class {
420 my $self = shift;
421 @_ ? $self->{'class'} = shift : $self->{'class'};
425 =head2 delete
427 $attr_type->delete();
428 C4::Members::AttributeTypes->delete($code);
430 Delete an attribute type from the database. The attribute
431 type may be specified either by an object or by a code.
433 =cut
435 sub delete {
436 my $arg = shift;
437 my $code;
438 if (ref($arg) eq __PACKAGE__) {
439 $code = $arg->{'code'};
440 } else {
441 $code = shift;
444 my $dbh = C4::Context->dbh;
445 my $sth = $dbh->prepare_cached("DELETE FROM borrower_attribute_types WHERE code = ?");
446 $sth->execute($code);
447 $sth->finish;
450 =head2 num_patrons
452 my $count = $attr_type->num_patrons();
454 Returns the number of patron records that use
455 this attribute type.
457 =cut
459 sub num_patrons {
460 my $self = shift;
462 my $dbh = C4::Context->dbh;
463 my $sth = $dbh->prepare_cached("SELECT COUNT(DISTINCT borrowernumber)
464 FROM borrower_attributes
465 WHERE code = ?");
466 $sth->execute($self->{code});
467 my ($count) = $sth->fetchrow_array;
468 $sth->finish;
469 return $count;
472 =head2 get_patrons
474 my @borrowernumbers = $attr_type->get_patrons($attribute);
476 Returns the borrowernumber of the patron records that
477 have an attribute with the specifie value.
479 =cut
481 sub get_patrons {
482 my $self = shift;
483 my $value = shift;
485 my $dbh = C4::Context->dbh;
486 my $sth = $dbh->prepare_cached("SELECT DISTINCT borrowernumber
487 FROM borrower_attributes
488 WHERE code = ?
489 AND attribute = ?");
490 $sth->execute($self->{code}, $value);
491 my @results;
492 while (my ($borrowernumber) = $sth->fetchrow_array) {
493 push @results, $borrowernumber;
495 return @results;
498 =head1 AUTHOR
500 Koha Development Team <http://koha-community.org/>
502 Galen Charlton <galen.charlton@liblime.com>
504 =cut