params => [
{desc => 'Authentication token', type => 'string'},
{desc => 'User ID', type => 'number'},
+ {desc => 'prefix', type => 'string'},
],
return => {desc => 'Generated barcode on success'}
}
);
-# evergreen.lu_update_barcode(user-id) generates a barcode, creates an actor.card
-# object, and points actor.usr.card to the new actor.card.id
+# evergreen.actor_update_barcode(user_id[, prefix]) generates a barcode, creates
+# an actor.card object, and points actor.usr.card to the new actor.card.id;
+# prefix is an optional prefix for the barcode
#
-# evergreen.lu_generate_barcode() just generates a barcode
+# evergreen.actor_generate_barcode([prefix]) just generates a barcode, with
+# prefix as an optional prefix for the barcode
sub generate_patron_barcode {
- my( $self, $client, $auth, $user_id ) = @_;
+ my( $self, $client, $auth, $user_id, $prefix ) = @_;
my $e = new_editor( authtoken=>$auth );
return $e->die_event unless $e->checkauth;
my $barcode;
if ($user_id) {
return $e->die_event unless $e->allowed('UPDATE_USER');
+ my $args = ['evergreen.actor_update_barcode', $user_id];
+ if ($prefix) {
+ push @$args, $prefix;
+ }
$barcode = $e->json_query(
- {from => ['evergreen.lu_update_barcode', $user_id]})->[0]
+ {from => $args})->[0]
or return $e->die_event;
} else {
+ my $args = ['evergreen.actor_generate_barcode'];
+ if ($prefix) {
+ push @$args, $prefix;
+ }
$barcode = $e->json_query(
- {from => ['evergreen.lu_generate_barcode']})->[0]
+ {from => $args})->[0]
or return $e->die_event;
}
--- /dev/null
+-- Provides support for generating patron barcodes, with optional prefixes
+-- If all digits, then a mod10 check digit is calculated and appended
+CREATE SEQUENCE evergreen.actor_barcode_seq;
+
+CREATE OR REPLACE FUNCTION evergreen.mod10(barcode TEXT)
+RETURNS TEXT AS $$
+use strict;
+use warnings;
+
+my $barcode = shift;
+my $total = 0;
+my $position = 0;
+foreach my $digit (split('', $barcode)) {
+ $digit = sprintf('%d', $digit);
+ $position++;
+ if ($position % 2) {
+ # Double it
+ $digit *= 2;
+ # If less than 10, add to the total
+ if ($digit < 10) {
+ $total += $digit;
+ } else {
+ $total += $digit - 9;
+ }
+ } else {
+ $total += $digit;
+ }
+}
+my $rem = $total % 10;
+if ($rem) {
+ return 10 - $rem;
+}
+return $rem;
+$$ LANGUAGE plperlu;
+
+CREATE OR REPLACE FUNCTION evergreen.actor_generate_barcode(prefix TEXT DEFAULT 'AUTOBC')
+RETURNS TEXT AS $$
+DECLARE
+ bc_gen TEXT;
+ mod TEXT;
+ bc_serial RECORD;
+ bc_holder TEXT;
+BEGIN
+ LOOP
+ SELECT lpad(NEXTVAL('evergreen.actor_barcode_seq')::text, 7, '0') AS bc INTO bc_serial;
+ bc_gen := rpad(COALESCE(prefix, '0'), 6, '0') || bc_serial.bc::text;
+ IF unnest(regexp_matches(bc_gen, '\D')) IS NOT NULL THEN
+ bc_gen := rpad(bc_gen, 14, '0');
+ ELSE
+ bc_gen := bc_gen || evergreen.mod10(bc_gen);
+ END IF;
+
+ SELECT barcode INTO bc_holder FROM actor.card WHERE barcode = bc_gen;
+ EXIT WHEN bc_holder IS NULL;
+ END LOOP;
+
+ RETURN bc_gen;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION evergreen.actor_update_barcode(usr_id INT, prefix TEXT DEFAULT NULL)
+RETURNS TEXT AS $$
+DECLARE
+ bc_gen TEXT;
+ bc_holder TEXT;
+BEGIN
+
+ LOOP
+ IF prefix IS NULL THEN
+ bc_gen := evergreen.actor_generate_barcode();
+ ELSE
+ bc_gen := evergreen.actor_generate_barcode(prefix);
+ END IF;
+
+ SELECT barcode INTO bc_holder FROM actor.card WHERE barcode = bc_gen;
+ EXIT WHEN bc_holder IS NULL;
+ END LOOP;
+
+ INSERT INTO actor.card (usr, barcode) VALUES (usr_id, bc_gen);
+
+ UPDATE actor.usr
+ SET card = CURRVAL('actor.card_id_seq')
+ WHERE id = usr_id;
+
+ RETURN bc_gen;
+END;
+$$ LANGUAGE plpgsql;