View | Details | Raw Unified | Return to bug 41728
Collapse All | Expand All

(-)a/Koha/Availability/Result.pm (+239 lines)
Line 0 Link Here
1
package Koha::Availability::Result;
2
3
# Copyright 2026 Koha Development Team
4
#
5
# This file is part of Koha.
6
#
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.
11
#
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.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <https://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
=head1 NAME
23
24
Koha::Availability::Result - Base class for availability check results
25
26
=head1 SYNOPSIS
27
28
    my $result = Koha::Availability::Result->new();
29
30
    $result->add_blocker( BadBarcode => $barcode );
31
    $result->add_confirmation( NotIssued => $barcode );
32
    $result->add_warning( withdrawn => 1 );
33
34
    if ( $result->available ) {
35
        # Proceed with action
36
    }
37
38
=head1 DESCRIPTION
39
40
This class provides a standardized structure for availability check results
41
across different operations (check-in, checkout, hold, renewal, etc.).
42
43
Results are categorized into:
44
- blockers: Conditions that prevent the action
45
- confirmations: Conditions requiring user confirmation
46
- warnings: Informational messages that don't prevent the action
47
48
=head1 API
49
50
=head2 Class methods
51
52
=head3 new
53
54
    my $result = Koha::Availability::Result->new();
55
56
Constructor. Creates a new result object with empty blockers, confirmations,
57
and warnings.
58
59
=cut
60
61
sub new {
62
    my ($class) = @_;
63
64
    my $self = {
65
        blockers      => {},
66
        confirmations => {},
67
        warnings      => {},
68
        context       => {},
69
    };
70
71
    return bless $self, $class;
72
}
73
74
=head2 Instance methods
75
76
=head3 add_blocker
77
78
    $result->add_blocker( $key => $value );
79
80
Adds a blocker. Blockers prevent the action from proceeding.
81
82
=cut
83
84
sub add_blocker {
85
    my ( $self, $key, $value ) = @_;
86
    $self->{blockers}->{$key} = $value;
87
    return $self;
88
}
89
90
=head3 add_confirmation
91
92
    $result->add_confirmation( $key => $value );
93
94
Adds a confirmation requirement. Confirmations require user acknowledgment
95
before proceeding.
96
97
=cut
98
99
sub add_confirmation {
100
    my ( $self, $key, $value ) = @_;
101
    $self->{confirmations}->{$key} = $value;
102
    return $self;
103
}
104
105
=head3 add_warning
106
107
    $result->add_warning( $key => $value );
108
109
Adds a warning. Warnings are informational and don't prevent the action.
110
111
=cut
112
113
sub add_warning {
114
    my ( $self, $key, $value ) = @_;
115
    $self->{warnings}->{$key} = $value;
116
    return $self;
117
}
118
119
=head3 set_context
120
121
    $result->set_context( $key => $value );
122
123
Sets a context value. Context provides additional information about the
124
availability check (e.g., related objects like item, checkout, patron).
125
126
=cut
127
128
sub set_context {
129
    my ( $self, $key, $value ) = @_;
130
    $self->{context}->{$key} = $value;
131
    return $self;
132
}
133
134
=head3 available
135
136
    if ( $result->available ) { ... }
137
138
Returns true if there are no blockers, false otherwise.
139
140
=cut
141
142
sub available {
143
    my ($self) = @_;
144
    return keys %{ $self->{blockers} } == 0;
145
}
146
147
=head3 needs_confirmation
148
149
    if ( $result->needs_confirmation ) { ... }
150
151
Returns true if there are confirmations required, false otherwise.
152
153
=cut
154
155
sub needs_confirmation {
156
    my ($self) = @_;
157
    return keys %{ $self->{confirmations} } > 0;
158
}
159
160
=head3 blockers
161
162
    my $blockers = $result->blockers;
163
164
Returns the blockers hashref.
165
166
=cut
167
168
sub blockers {
169
    my ($self) = @_;
170
    return $self->{blockers};
171
}
172
173
=head3 confirmations
174
175
    my $confirmations = $result->confirmations;
176
177
Returns the confirmations hashref.
178
179
=cut
180
181
sub confirmations {
182
    my ($self) = @_;
183
    return $self->{confirmations};
184
}
185
186
=head3 warnings
187
188
    my $warnings = $result->warnings;
189
190
Returns the warnings hashref.
191
192
=cut
193
194
sub warnings {
195
    my ($self) = @_;
196
    return $self->{warnings};
197
}
198
199
=head3 context
200
201
    my $context = $result->context;
202
    my $item = $result->context->{item};
203
204
Returns the context hashref.
205
206
=cut
207
208
sub context {
209
    my ($self) = @_;
210
    return $self->{context};
211
}
212
213
=head3 to_hashref
214
215
    my $hashref = $result->to_hashref;
216
217
Returns a plain hashref representation of the result, suitable for
218
backward compatibility or serialization.
219
220
=cut
221
222
sub to_hashref {
223
    my ($self) = @_;
224
225
    return {
226
        blockers => $self->{blockers},
227
        confirms => $self->{confirmations},
228
        warnings => $self->{warnings},
229
        %{ $self->{context} },
230
    };
231
}
232
233
=head1 AUTHOR
234
235
Koha Development Team <https://koha-community.org/>
236
237
=cut
238
239
1;
(-)a/t/Koha/Availability/Result.t (-1 / +141 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2026 Koha Development team
4
#
5
# This file is part of Koha
6
#
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.
11
#
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.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <https://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 9;
23
use Test::NoWarnings;
24
25
use Koha::Availability::Result;
26
27
subtest 'new() creates empty result' => sub {
28
29
    plan tests => 5;
30
31
    my $result = Koha::Availability::Result->new();
32
33
    isa_ok( $result, 'Koha::Availability::Result', 'new() returns Result object' );
34
    is( ref( $result->blockers ),      'HASH', 'blockers is a hashref' );
35
    is( ref( $result->confirmations ), 'HASH', 'confirmations is a hashref' );
36
    is( ref( $result->warnings ),      'HASH', 'warnings is a hashref' );
37
    is( ref( $result->context ),       'HASH', 'context is a hashref' );
38
};
39
40
subtest 'add_blocker()' => sub {
41
42
    plan tests => 3;
43
44
    my $result = Koha::Availability::Result->new();
45
46
    $result->add_blocker( test_blocker => 'value' );
47
48
    is( $result->blockers->{test_blocker}, 'value', 'blocker added' );
49
    is( keys %{ $result->blockers },       1,       'one blocker present' );
50
    isa_ok( $result->add_blocker( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' );
51
};
52
53
subtest 'add_confirmation()' => sub {
54
55
    plan tests => 3;
56
57
    my $result = Koha::Availability::Result->new();
58
59
    $result->add_confirmation( test_confirm => 'value' );
60
61
    is( $result->confirmations->{test_confirm}, 'value', 'confirmation added' );
62
    is( keys %{ $result->confirmations },       1,       'one confirmation present' );
63
    isa_ok( $result->add_confirmation( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' );
64
};
65
66
subtest 'add_warning()' => sub {
67
68
    plan tests => 3;
69
70
    my $result = Koha::Availability::Result->new();
71
72
    $result->add_warning( test_warning => 'value' );
73
74
    is( $result->warnings->{test_warning}, 'value', 'warning added' );
75
    is( keys %{ $result->warnings },       1,       'one warning present' );
76
    isa_ok( $result->add_warning( another => 1 ), 'Koha::Availability::Result', 'returns self for chaining' );
77
};
78
79
subtest 'set_context()' => sub {
80
81
    plan tests => 3;
82
83
    my $result = Koha::Availability::Result->new();
84
85
    $result->set_context( item => 'test_item' );
86
87
    is( $result->context->{item},   'test_item', 'context value set' );
88
    is( keys %{ $result->context }, 1,           'one context value present' );
89
    isa_ok(
90
        $result->set_context( patron => 'test_patron' ), 'Koha::Availability::Result',
91
        'returns self for chaining'
92
    );
93
};
94
95
subtest 'available()' => sub {
96
97
    plan tests => 2;
98
99
    my $result = Koha::Availability::Result->new();
100
101
    ok( $result->available, 'available when no blockers' );
102
103
    $result->add_blocker( test => 1 );
104
105
    ok( !$result->available, 'not available when blockers present' );
106
};
107
108
subtest 'needs_confirmation()' => sub {
109
110
    plan tests => 2;
111
112
    my $result = Koha::Availability::Result->new();
113
114
    ok( !$result->needs_confirmation, 'no confirmation needed when empty' );
115
116
    $result->add_confirmation( test => 1 );
117
118
    ok( $result->needs_confirmation, 'confirmation needed when confirmations present' );
119
};
120
121
subtest 'to_hashref()' => sub {
122
123
    plan tests => 6;
124
125
    my $result = Koha::Availability::Result->new();
126
127
    $result->add_blocker( blocker1 => 'b1' );
128
    $result->add_confirmation( confirm1 => 'c1' );
129
    $result->add_warning( warning1 => 'w1' );
130
    $result->set_context( item   => 'test_item' );
131
    $result->set_context( patron => 'test_patron' );
132
133
    my $hashref = $result->to_hashref();
134
135
    is( ref($hashref),                    'HASH',        'returns hashref' );
136
    is( $hashref->{blockers}->{blocker1}, 'b1',          'blockers included' );
137
    is( $hashref->{confirms}->{confirm1}, 'c1',          'confirmations included as confirms' );
138
    is( $hashref->{warnings}->{warning1}, 'w1',          'warnings included' );
139
    is( $hashref->{item},                 'test_item',   'context item included at top level' );
140
    is( $hashref->{patron},               'test_patron', 'context patron included at top level' );
141
};

Return to bug 41728