Bugzilla – Attachment 192130 Details for
Bug 41728
Add `Koha::Item::Checkin::Availability` to centralize logic
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 41728: Add Koha::Availability::Result base class
d76de98.patch (text/plain), 11.44 KB, created by
Tomás Cohen Arazi (tcohen)
on 2026-01-28 19:12:29 UTC
(
hide
)
Description:
Bug 41728: Add Koha::Availability::Result base class
Filename:
MIME Type:
Creator:
Tomás Cohen Arazi (tcohen)
Created:
2026-01-28 19:12:29 UTC
Size:
11.44 KB
patch
obsolete
>From d76de98a1bc627105b390b3f5ac8548ba3d415e4 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Tom=C3=A1s=20Cohen=20Arazi?= <tomascohen@theke.io> >Date: Wed, 28 Jan 2026 15:33:54 -0300 >Subject: [PATCH] Bug 41728: Add Koha::Availability::Result base class > >This patch introduces a standardized result class for availability checks, >providing a clean API with proper methods instead of raw hashrefs. > >The Koha::Availability::Result class provides: >- add_blocker() - Add conditions that prevent the action >- add_confirmation() - Add conditions requiring user confirmation >- add_warning() - Add informational messages >- set_context() - Store related objects (item, checkout, patron, etc.) >- available() - Check if action can proceed (no blockers) >- needs_confirmation() - Check if confirmations are required >- Accessor methods for all categories >- to_hashref() for backward compatibility > >This design: >- Provides a consistent interface across all availability checks >- Makes the API more discoverable and self-documenting >- Enables future enhancements without breaking changes >- Follows OO principles with proper encapsulation >- Can be used as base for checkout, hold, renewal availability > >Test plan: >1. Apply patch >2. Run: > $ ktd --shell > k$ prove t/Koha/Availability/Result.t >=> SUCCESS: Tests pass! >3. Verify all methods work correctly >4. Sign off :-D >--- > Koha/Availability/Result.pm | 239 +++++++++++++++++++++++++++++++++++ > t/Koha/Availability/Result.t | 141 +++++++++++++++++++++ > 2 files changed, 380 insertions(+) > create mode 100644 Koha/Availability/Result.pm > create mode 100755 t/Koha/Availability/Result.t > >diff --git a/Koha/Availability/Result.pm b/Koha/Availability/Result.pm >new file mode 100644 >index 0000000000..8c48049a3c >--- /dev/null >+++ b/Koha/Availability/Result.pm >@@ -0,0 +1,239 @@ >+package Koha::Availability::Result; >+ >+# Copyright 2026 Koha Development Team >+# >+# This file is part of Koha. >+# >+# 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 Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# 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 A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <https://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::Availability::Result - Base class for availability check results >+ >+=head1 SYNOPSIS >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->add_blocker( BadBarcode => $barcode ); >+ $result->add_confirmation( NotIssued => $barcode ); >+ $result->add_warning( withdrawn => 1 ); >+ >+ if ( $result->available ) { >+ # Proceed with action >+ } >+ >+=head1 DESCRIPTION >+ >+This class provides a standardized structure for availability check results >+across different operations (check-in, checkout, hold, renewal, etc.). >+ >+Results are categorized into: >+- blockers: Conditions that prevent the action >+- confirmations: Conditions requiring user confirmation >+- warnings: Informational messages that don't prevent the action >+ >+=head1 API >+ >+=head2 Class methods >+ >+=head3 new >+ >+ my $result = Koha::Availability::Result->new(); >+ >+Constructor. Creates a new result object with empty blockers, confirmations, >+and warnings. >+ >+=cut >+ >+sub new { >+ my ($class) = @_; >+ >+ my $self = { >+ blockers => {}, >+ confirmations => {}, >+ warnings => {}, >+ context => {}, >+ }; >+ >+ return bless $self, $class; >+} >+ >+=head2 Instance methods >+ >+=head3 add_blocker >+ >+ $result->add_blocker( $key => $value ); >+ >+Adds a blocker. Blockers prevent the action from proceeding. >+ >+=cut >+ >+sub add_blocker { >+ my ( $self, $key, $value ) = @_; >+ $self->{blockers}->{$key} = $value; >+ return $self; >+} >+ >+=head3 add_confirmation >+ >+ $result->add_confirmation( $key => $value ); >+ >+Adds a confirmation requirement. Confirmations require user acknowledgment >+before proceeding. >+ >+=cut >+ >+sub add_confirmation { >+ my ( $self, $key, $value ) = @_; >+ $self->{confirmations}->{$key} = $value; >+ return $self; >+} >+ >+=head3 add_warning >+ >+ $result->add_warning( $key => $value ); >+ >+Adds a warning. Warnings are informational and don't prevent the action. >+ >+=cut >+ >+sub add_warning { >+ my ( $self, $key, $value ) = @_; >+ $self->{warnings}->{$key} = $value; >+ return $self; >+} >+ >+=head3 set_context >+ >+ $result->set_context( $key => $value ); >+ >+Sets a context value. Context provides additional information about the >+availability check (e.g., related objects like item, checkout, patron). >+ >+=cut >+ >+sub set_context { >+ my ( $self, $key, $value ) = @_; >+ $self->{context}->{$key} = $value; >+ return $self; >+} >+ >+=head3 available >+ >+ if ( $result->available ) { ... } >+ >+Returns true if there are no blockers, false otherwise. >+ >+=cut >+ >+sub available { >+ my ($self) = @_; >+ return keys %{ $self->{blockers} } == 0; >+} >+ >+=head3 needs_confirmation >+ >+ if ( $result->needs_confirmation ) { ... } >+ >+Returns true if there are confirmations required, false otherwise. >+ >+=cut >+ >+sub needs_confirmation { >+ my ($self) = @_; >+ return keys %{ $self->{confirmations} } > 0; >+} >+ >+=head3 blockers >+ >+ my $blockers = $result->blockers; >+ >+Returns the blockers hashref. >+ >+=cut >+ >+sub blockers { >+ my ($self) = @_; >+ return $self->{blockers}; >+} >+ >+=head3 confirmations >+ >+ my $confirmations = $result->confirmations; >+ >+Returns the confirmations hashref. >+ >+=cut >+ >+sub confirmations { >+ my ($self) = @_; >+ return $self->{confirmations}; >+} >+ >+=head3 warnings >+ >+ my $warnings = $result->warnings; >+ >+Returns the warnings hashref. >+ >+=cut >+ >+sub warnings { >+ my ($self) = @_; >+ return $self->{warnings}; >+} >+ >+=head3 context >+ >+ my $context = $result->context; >+ my $item = $result->context->{item}; >+ >+Returns the context hashref. >+ >+=cut >+ >+sub context { >+ my ($self) = @_; >+ return $self->{context}; >+} >+ >+=head3 to_hashref >+ >+ my $hashref = $result->to_hashref; >+ >+Returns a plain hashref representation of the result, suitable for >+backward compatibility or serialization. >+ >+=cut >+ >+sub to_hashref { >+ my ($self) = @_; >+ >+ return { >+ blockers => $self->{blockers}, >+ confirms => $self->{confirmations}, >+ warnings => $self->{warnings}, >+ %{ $self->{context} }, >+ }; >+} >+ >+=head1 AUTHOR >+ >+Koha Development Team <https://koha-community.org/> >+ >+=cut >+ >+1; >diff --git a/t/Koha/Availability/Result.t b/t/Koha/Availability/Result.t >new file mode 100755 >index 0000000000..2d3059f356 >--- /dev/null >+++ b/t/Koha/Availability/Result.t >@@ -0,0 +1,141 @@ >+#!/usr/bin/perl >+ >+# Copyright 2026 Koha Development team >+# >+# This file is part of Koha >+# >+# 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 Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# 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 A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <https://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Test::More tests => 9; >+use Test::NoWarnings; >+ >+use Koha::Availability::Result; >+ >+subtest 'new() creates empty result' => sub { >+ >+ plan tests => 5; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ isa_ok( $result, 'Koha::Availability::Result', 'new() returns Result object' ); >+ is( ref( $result->blockers ), 'HASH', 'blockers is a hashref' ); >+ is( ref( $result->confirmations ), 'HASH', 'confirmations is a hashref' ); >+ is( ref( $result->warnings ), 'HASH', 'warnings is a hashref' ); >+ is( ref( $result->context ), 'HASH', 'context is a hashref' ); >+}; >+ >+subtest 'add_blocker()' => sub { >+ >+ plan tests => 3; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->add_blocker( test_blocker => 'value' ); >+ >+ is( $result->blockers->{test_blocker}, 'value', 'blocker added' ); >+ is( keys %{ $result->blockers }, 1, 'one blocker present' ); >+ isa_ok( $result->add_blocker( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' ); >+}; >+ >+subtest 'add_confirmation()' => sub { >+ >+ plan tests => 3; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->add_confirmation( test_confirm => 'value' ); >+ >+ is( $result->confirmations->{test_confirm}, 'value', 'confirmation added' ); >+ is( keys %{ $result->confirmations }, 1, 'one confirmation present' ); >+ isa_ok( $result->add_confirmation( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' ); >+}; >+ >+subtest 'add_warning()' => sub { >+ >+ plan tests => 3; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->add_warning( test_warning => 'value' ); >+ >+ is( $result->warnings->{test_warning}, 'value', 'warning added' ); >+ is( keys %{ $result->warnings }, 1, 'one warning present' ); >+ isa_ok( $result->add_warning( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' ); >+}; >+ >+subtest 'set_context()' => sub { >+ >+ plan tests => 3; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->set_context( item => 'test_item' ); >+ >+ is( $result->context->{item}, 'test_item', 'context value set' ); >+ is( keys %{ $result->context }, 1, 'one context value present' ); >+ isa_ok( >+ $result->set_context( patron => 'test_patron' ), 'Koha::Availability::Result', >+ 'returns self for chaining' >+ ); >+}; >+ >+subtest 'available()' => sub { >+ >+ plan tests => 2; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ ok( $result->available, 'available when no blockers' ); >+ >+ $result->add_blocker( test => 1 ); >+ >+ ok( !$result->available, 'not available when blockers present' ); >+}; >+ >+subtest 'needs_confirmation()' => sub { >+ >+ plan tests => 2; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ ok( !$result->needs_confirmation, 'no confirmation needed when empty' ); >+ >+ $result->add_confirmation( test => 1 ); >+ >+ ok( $result->needs_confirmation, 'confirmation needed when confirmations present' ); >+}; >+ >+subtest 'to_hashref()' => sub { >+ >+ plan tests => 6; >+ >+ my $result = Koha::Availability::Result->new(); >+ >+ $result->add_blocker( blocker1 => 'b1' ); >+ $result->add_confirmation( confirm1 => 'c1' ); >+ $result->add_warning( warning1 => 'w1' ); >+ $result->set_context( item => 'test_item' ); >+ $result->set_context( patron => 'test_patron' ); >+ >+ my $hashref = $result->to_hashref(); >+ >+ is( ref($hashref), 'HASH', 'returns hashref' ); >+ is( $hashref->{blockers}->{blocker1}, 'b1', 'blockers included' ); >+ is( $hashref->{confirms}->{confirm1}, 'c1', 'confirmations included as confirms' ); >+ is( $hashref->{warnings}->{warning1}, 'w1', 'warnings included' ); >+ is( $hashref->{item}, 'test_item', 'context item included at top level' ); >+ is( $hashref->{patron}, 'test_patron', 'context patron included at top level' ); >+}; >-- >2.50.1 (Apple Git-155) >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 41728
: 192130 |
192131
|
192132
|
192133