library: barcode modes, patrons/lending, install-time shelves and item types
Quick Add: - barcode choices: automatic (zero-padded, >= 7 digits), scan a pre-printed sticker per item, or none for now; bulk 'give barcodes to items without one'; reserve a block of numbers and print the sheet ahead of time (link opens Koha's range printer prefilled) - default shelf saved on the server (shared by every device) - item types follow Koha; CSP allows cover redirects; aria attrs fixed Koha bootstrap: - default lending rule (3 weeks, 25 items, 3 renewals, no fines) - a fresh Koha refuses every checkout without one - automatic library-card numbers (start at 1000001), fines off - Koha's own auto-barcode off (one numbering scheme) - patron card template (Avery 5371) and layout with a scannable barcode - LIBRARY_CODE, SHELVES and ITEM_TYPES honoured at first install Why 7 digits: decoded printed sheets - 7-digit Code 39 read back 40/40, 6-digit all-numeric symbols were reinterpreted as Code 32 for ~1 in 10 values. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013wi3ZSot4XbUViwRFgLpRf
This commit is contained in:
@@ -11,6 +11,9 @@ use Koha;
|
||||
use Koha::Libraries;
|
||||
use Koha::Patrons;
|
||||
use Koha::Patron::Categories;
|
||||
use Koha::CirculationRules;
|
||||
use Koha::ItemTypes;
|
||||
use Koha::AuthorisedValues;
|
||||
|
||||
$| = 1;
|
||||
my $seed_dir = $ENV{KOHA_SEED_DIR} || '/opt/koha-init/seed';
|
||||
@@ -20,6 +23,7 @@ my %env = (
|
||||
admin_user => $ENV{KOHA_ADMIN_USER} || 'admin',
|
||||
admin_pass => $admin_pass,
|
||||
library => $ENV{KOHA_LIBRARY_NAME} || 'My Library',
|
||||
code => uc( ( $ENV{KOHA_LIBRARY_CODE} || 'HOME' ) =~ s/[^A-Za-z0-9]//gr ) || 'HOME',
|
||||
);
|
||||
|
||||
my $installer = C4::Installer->new();
|
||||
@@ -74,8 +78,8 @@ for my $y (sort glob("$seed_dir/*.yml")) {
|
||||
|
||||
# ---- Library, patron categories, owner account ----------------------------
|
||||
Koha::Library->new({
|
||||
branchcode => 'HOME', branchname => $env{library},
|
||||
})->store unless Koha::Libraries->find('HOME');
|
||||
branchcode => $env{code}, branchname => $env{library},
|
||||
})->store unless Koha::Libraries->find( $env{code} );
|
||||
|
||||
for my $c ( [ 'OWNER', 'Owner / librarian', 'S' ], [ 'FRIEND', 'Friend / borrower', 'A' ] ) {
|
||||
Koha::Patron::Category->new({
|
||||
@@ -85,8 +89,8 @@ for my $c ( [ 'OWNER', 'Owner / librarian', 'S' ], [ 'FRIEND', 'Friend / borrowe
|
||||
}
|
||||
|
||||
my $admin = Koha::Patron->new({
|
||||
cardnumber => 'ADMIN', surname => 'Librarian', userid => $env{admin_user},
|
||||
branchcode => 'HOME', categorycode => 'OWNER', flags => 1, # 1 = superlibrarian
|
||||
cardnumber => '1000000', surname => 'Librarian', userid => $env{admin_user},
|
||||
branchcode => $env{code}, categorycode => 'OWNER', flags => 1, # 1 = superlibrarian
|
||||
})->store;
|
||||
$admin->set_password({ password => $env{admin_pass}, skip_validation => 1 });
|
||||
|
||||
@@ -102,9 +106,58 @@ $dbh->do(q{UPDATE marc_subfield_structure SET defaultvalue = 'BOOK'
|
||||
$dbh->do(q{UPDATE marc_subfield_structure SET kohafield = 'biblioitems.ean'
|
||||
WHERE tagfield = '024' AND tagsubfield = 'a' AND (kohafield IS NULL OR kohafield = '')});
|
||||
|
||||
# ---- Extra item types and shelves chosen at install time -------------------
|
||||
# KOHA_ITEM_TYPES / KOHA_SHELVES: "CODE=Description;CODE=Description". Koha has no
|
||||
# API for adding shelves later, so they are declared here (more can be added in
|
||||
# Administration -> Authorized values -> LOC).
|
||||
sub pairs {
|
||||
my ($raw) = @_;
|
||||
return map { my ( $c, $d ) = split /=/, $_, 2; $c =~ s/[^A-Za-z0-9_]//g; ( uc $c, ( $d // $c ) =~ s/^\s+|\s+$//gr ) }
|
||||
grep { /\S/ } split /;/, ( $raw // '' );
|
||||
}
|
||||
{
|
||||
my @t = pairs( $ENV{KOHA_ITEM_TYPES} );
|
||||
while ( my ( $c, $d ) = splice @t, 0, 2 ) {
|
||||
next unless length $c;
|
||||
Koha::ItemType->new( { itemtype => substr( $c, 0, 10 ), description => $d } )->store
|
||||
unless Koha::ItemTypes->find( substr( $c, 0, 10 ) );
|
||||
}
|
||||
my @s = pairs( $ENV{KOHA_SHELVES} );
|
||||
while ( my ( $c, $d ) = splice @s, 0, 2 ) {
|
||||
next unless length $c;
|
||||
Koha::AuthorisedValue->new( { category => 'LOC', authorised_value => substr( $c, 0, 80 ), lib => $d, lib_opac => $d } )->store
|
||||
unless Koha::AuthorisedValues->search( { category => 'LOC', authorised_value => substr( $c, 0, 80 ) } )->count;
|
||||
}
|
||||
}
|
||||
|
||||
# ---- Lending rules --------------------------------------------------------
|
||||
# A fresh Koha refuses every checkout ("No circulation rule is defined for this
|
||||
# patron and itemtype combination") until a default rule exists. One catch-all
|
||||
# rule for a home library: 3 weeks, 25 items, 3 renewals, no fines.
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef, categorycode => undef, itemtype => undef,
|
||||
rules => {
|
||||
issuelength => 21, lengthunit => 'days', maxissueqty => 25, maxonsiteissueqty => '',
|
||||
renewalsallowed => 3, renewalperiod => 21, norenewalbefore => '', noautorenewalbefore => '',
|
||||
auto_renew => 0, no_auto_renewal_after => '', no_auto_renewal_after_hard_limit => '',
|
||||
unseen_renewals_allowed => '',
|
||||
fine => 0, finedays => 0, firstremind => 0, chargeperiod => 0, chargeperiod_charge_at => 0,
|
||||
overduefinescap => '', cap_fine_to_replacement_price => 0, rentaldiscount => 0,
|
||||
maxsuspensiondays => '', suspension_chargeperiod => 1,
|
||||
hardduedate => '', hardduedatecompare => -1,
|
||||
reservesallowed => 5, holds_per_record => 1, holds_per_day => '', onshelfholds => 1,
|
||||
opacitemholds => 'N', decreaseloanholds => '', article_requests => 'no',
|
||||
recalls_allowed => undef, recalls_per_record => undef, on_shelf_recalls => undef,
|
||||
recall_due_date_interval => undef, recall_overdue_fine => undef,
|
||||
recall_shelf_time => undef, holds_pickup_period => undef,
|
||||
},
|
||||
});
|
||||
|
||||
# ---- Preferences ----------------------------------------------------------
|
||||
my %prefs = (
|
||||
autoBarcode => 'incremental', # new items get a barcode automatically
|
||||
autoBarcode => 'OFF', # barcodes are assigned by Quick Add (zero-padded, or none/scanned on request)
|
||||
autoMemberNum => 1, # new patrons get the next library-card number automatically
|
||||
finesMode => 'off', # a home library does not charge overdue fines
|
||||
itemcallnumber => '082ab', # Dewey call number copied from the MARC record
|
||||
RESTBasicAuth => 1, # lets the quick-add page use the REST API
|
||||
OpenLibraryCovers => 1, # cover images in the catalogue
|
||||
|
||||
@@ -81,7 +81,8 @@ if [ "$TABLES" = "0" ]; then
|
||||
runuser -u "$INST-koha" -- env \
|
||||
KOHA_CONF="/etc/koha/sites/$INST/koha-conf.xml" PERL5LIB=/usr/share/koha/lib \
|
||||
KOHA_ADMIN_USER="${KOHA_ADMIN_USER:-admin}" KOHA_ADMIN_PASS="$KOHA_ADMIN_PASS" \
|
||||
KOHA_LIBRARY_NAME="${KOHA_LIBRARY_NAME:-My Library}" TZ="$TZ" \
|
||||
KOHA_LIBRARY_NAME="${KOHA_LIBRARY_NAME:-My Library}" KOHA_LIBRARY_CODE="${KOHA_LIBRARY_CODE:-HOME}" \
|
||||
KOHA_SHELVES="${KOHA_SHELVES:-}" KOHA_ITEM_TYPES="${KOHA_ITEM_TYPES:-}" TZ="$TZ" \
|
||||
perl /opt/koha-init/bootstrap.pl
|
||||
TABLES=$(mariadb -N -h "$DB_HOST" -u "$DB_USER" -p"$KOHA_DB_PASS" "$DB_NAME" \
|
||||
-e "select count(*) from information_schema.tables where table_schema='$DB_NAME'")
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
description:
|
||||
- "Library card sheet and layout for Tools > Patron card creator"
|
||||
tables:
|
||||
- creator_templates:
|
||||
translatable: [ template_desc ]
|
||||
multiline: [ ]
|
||||
rows:
|
||||
# Avery 5371 / 8871 business-card sheet: 10 cards, 2 across x 5 down.
|
||||
- template_code: "Avery 5371 | 2 x 3-1/2 (10 per sheet)"
|
||||
template_desc: "Library cards: 2 columns, 5 rows."
|
||||
page_width: 8.5
|
||||
page_height: 11
|
||||
label_width: 3.5
|
||||
label_height: 2
|
||||
top_text_margin: 0
|
||||
left_text_margin: 0
|
||||
top_margin: 0.5
|
||||
left_margin: 0.75
|
||||
cols: 2
|
||||
rows: 5
|
||||
col_gap: 0
|
||||
row_gap: 0
|
||||
units: "INCH"
|
||||
creator: "Patroncards"
|
||||
|
||||
- creator_layouts:
|
||||
translatable: [ layout_name, layout_xml ]
|
||||
multiline: [ layout_xml ]
|
||||
rows:
|
||||
# Name and library at the top, card number as a scannable barcode.
|
||||
- layout_name: "Library card"
|
||||
barcode_type: CODE39
|
||||
start_label: 1
|
||||
printing_type: BAR
|
||||
guidebox: 0
|
||||
oblique_title: 0
|
||||
font: TR
|
||||
font_size: 10
|
||||
units: POINT
|
||||
callnum_split: 0
|
||||
text_justify: L
|
||||
format_string: "barcode"
|
||||
layout_xml:
|
||||
- "<opt page_side=\"F\" units=\"POINT\">"
|
||||
- " <text><firstname> <surname></text>"
|
||||
- " <text enable=\"1\" font=\"TB\" font_size=\"14\" llx=\"14\" lly=\"118\" text_alignment=\"L\" />"
|
||||
- " <text>Library card</text>"
|
||||
- " <text enable=\"1\" font=\"TR\" font_size=\"9\" llx=\"14\" lly=\"100\" text_alignment=\"L\" />"
|
||||
- " <barcode print=\"1\" type=\"CODE39\" llx=\"14\" lly=\"30\" height_scale=\"0.012\" width_scale=\"0.6\" text_print=\"1\" />"
|
||||
- "</opt>"
|
||||
creator: "Patroncards"
|
||||
Reference in New Issue
Block a user