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

(-)a/Koha/REST/V1/Suggestions.pm (-58 / +45 lines)
Lines 32-42 use Koha::Libraries; Link Here
32
use Try::Tiny;
32
use Try::Tiny;
33
33
34
sub list {
34
sub list {
35
    my ($c, $args, $cb) = @_;
35
    my $c = shift->openapi->valid_input or return;
36
36
37
    my $suggestions;
37
    my $suggestions;
38
    my $filter;
38
    my $filter;
39
    $args //= {};
39
    my $args = $c->validation->output;
40
40
41
    for my $filter_param ( keys %$args ) {
41
    for my $filter_param ( keys %$args ) {
42
        $filter->{$filter_param} = { LIKE => $args->{$filter_param} . '%' };
42
        $filter->{$filter_param} = { LIKE => $args->{$filter_param} . '%' };
Lines 44-98 sub list { Link Here
44
44
45
    return try {
45
    return try {
46
        $suggestions = Koha::Suggestions->search($filter)->unblessed;
46
        $suggestions = Koha::Suggestions->search($filter)->unblessed;
47
        return $c->$cb( $suggestions, 200 );
47
        return $c->render( status => 200, openapi => $suggestions );
48
    }
48
    }
49
    catch {
49
    catch {
50
        if ( $_->isa('DBIx::Class::Exception') ) {
50
        if ( $_->isa('DBIx::Class::Exception') ) {
51
            return $c->$cb( { error => $_->{msg} }, 500 );
51
            return $c->render( status => 500, openapi => { error => $_->{msg} } );
52
        }
52
        }
53
        else {
53
        else {
54
            return $c->$cb(
54
            return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } );
55
                { error => 'Something went wrong, check the logs.' }, 500 );
56
        }
55
        }
57
    };
56
    };
58
}
57
}
59
58
60
sub get {
59
sub get {
61
    my ($c, $args, $cb) = @_;
60
    my $c = shift->openapi->valid_input or return;
61
    my $args = $c->validation->output;
62
62
63
    my $suggestion = Koha::Suggestions->find($args->{suggestionid});
63
    my $suggestion = Koha::Suggestions->find($args->{suggestionid});
64
    unless ($suggestion) {
64
    unless ($suggestion) {
65
        return $c->$cb({error => 'Suggestion not found'}, 404);
65
        return $c->render( status => 404, openapi => {error => 'Suggestion not found'});
66
    }
66
    }
67
67
68
    return $c->$cb($suggestion->unblessed, 200);
68
    return $c->render( status => 200, openapi => $suggestion->unblessed );
69
}
69
}
70
70
71
sub add {
71
sub add {
72
    my ( $c, $args, $cb ) = @_;
72
    my $c = shift->openapi->valid_input or return;
73
73
    my $args = $c->validation->output;
74
    my $error = _validate_body($c, $args, $cb, 0);
75
    return $error if $error;
76
74
77
    my $suggestion = Koha::Suggestion->new( $args->{body} );
75
    my $suggestion = Koha::Suggestion->new( $args->{body} );
78
76
79
    return try {
77
    return try {
80
        $suggestion->store;
78
        $suggestion->store;
81
        return $c->$cb( $suggestion->unblessed, 200 );
79
        return $c->render( status => 200, openapi => $suggestion->unblessed );
82
    }
80
    }
83
    catch {
81
    catch {
84
        if ( $_->isa('DBIx::Class::Exception') ) {
82
        if ( $_->isa('DBIx::Class::Exception') ) {
85
            return $c->$cb( { error => $_->msg }, 500 );
83
            return $c->render( status => 500, openapi => { error => $_->msg } );
86
        }
84
        }
87
        else {
85
        else {
88
            return $c->$cb(
86
            return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } );
89
                { error => 'Something went wrong, check the logs.' }, 500 );
90
        }
87
        }
91
    };
88
    }
92
}
89
}
93
90
94
sub update {
91
sub update {
95
    my ( $c, $args, $cb ) = @_;
92
    my $c = shift->openapi->valid_input or return;
93
94
    my $args = $c->validation->output;
96
95
97
    my $suggestion;
96
    my $suggestion;
98
97
Lines 109-163 sub update { Link Here
109
            }
108
            }
110
        }
109
        }
111
110
112
        my $error = _validate_body($c, $args, $cb, 1);
113
        return $error if $error;
114
115
        $suggestion->set( $body );
111
        $suggestion->set( $body );
116
        $suggestion->store();
112
        $suggestion->store();
117
        return $c->$cb( $suggestion->unblessed, 200 );
113
        return $c->render( status => 200, openapi => $suggestion->unblessed );
118
    }
114
    }
119
    catch {
115
    catch {
120
        if ( not defined $suggestion ) {
116
        if ( not defined $suggestion ) {
121
            return $c->$cb( { error => 'Object not found' }, 404 );
117
            return $c->render( status => 404, openapi => { error => 'Object not found' } );
122
        }
118
        }
123
        elsif ( $_->isa('Koha::Exceptions::Object') ) {
119
        elsif ( $_->isa('Koha::Exceptions::Object') ) {
124
            return $c->$cb( { error => $_->message }, 500 );
120
            return $c->render( status => 500, openapi => { error => $_->message } );
125
        }
121
        }
126
        else {
122
        else {
127
            return $c->$cb(
123
            return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } );
128
                { error => 'Something went wrong, check the logs.' }, 500 );
129
        }
124
        }
130
    };
125
    };
131
126
132
}
127
}
133
128
134
sub delete {
129
sub delete {
135
    my ( $c, $args, $cb ) = @_;
130
    my $c = shift->openapi->valid_input or return;
131
132
    my $args = $c->validation->output;
136
133
137
    my $suggestion;
134
    my $suggestion;
138
135
139
    return try {
136
    return try {
140
        $suggestion = Koha::Suggestions->find( $args->{suggestionid} );
137
        $suggestion = Koha::Suggestions->find( $args->{suggestionid} );
141
        $suggestion->delete;
138
        $suggestion->delete;
142
        return $c->$cb( '', 200 );
139
        return $c->render( status => 200, openapi => '' );
143
    }
140
    }
144
    catch {
141
    catch {
145
        if ( not defined $suggestion ) {
142
        if ( not defined $suggestion ) {
146
            return $c->$cb( { error => 'Object not found' }, 404 );
143
            return $c->render( status => 404, openapi => { error => 'Object not found' } );
147
        }
144
        }
148
        elsif ( $_->isa('DBIx::Class::Exception') ) {
145
        elsif ( $_->isa('DBIx::Class::Exception') ) {
149
            return $c->$cb( { error => $_->msg }, 500 );
146
            return $c->render( status => 500, openapi => { error => $_->msg } );
150
        }
147
        }
151
        else {
148
        else {
152
            return $c->$cb(
149
            return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } );
153
                { error => 'Something went wrong, check the logs.' }, 500 );
154
        }
150
        }
155
    };
151
    };
156
152
157
}
153
}
158
154
159
sub _validate_body {
155
sub _validate_body {
160
    my ( $c, $args, $cb, $updating ) = @_;
156
    my $c = shift->openapi->valid_input or return;
157
158
    my $args = $c->validation->output;
161
159
162
    my $body = $args->{body};
160
    my $body = $args->{body};
163
    my $user = $c->stash('koha.user');
161
    my $user = $c->stash('koha.user');
Lines 177-201 sub _validate_body { Link Here
177
        foreach my $param ( keys %{ $body } ) {
175
        foreach my $param ( keys %{ $body } ) {
178
            unless (/^$param$/ ~~ @allowed_fields) {
176
            unless (/^$param$/ ~~ @allowed_fields) {
179
                # Ouch ! Some mandatory field is missing!
177
                # Ouch ! Some mandatory field is missing!
180
                my $verb = $updating ? 'updated ' : 'specified ';
178
                my $verb = 'specified ';
181
                return $c->$cb({error => 'You ' . $verb . $param . ', but allowed fields are only ' .
179
                return $c->render( status => 403 , openapi => {
182
                        join(', ', @allowed_fields)}, 403);
180
				error => 'You ' . $verb . $param . ', but allowed fields are only ' . join(', ', @allowed_fields)}
181
				 );
183
            }
182
            }
184
        }
183
        }
185
    }
184
    }
186
185
187
    if (not $updating) {
188
        # Check for missing fields
189
        my @mandatory_fields = split /,/, C4::Context->preference('OPACSuggestionMandatoryFields');
190
        my @missing_fields = ();
191
        for my $mandatory_field (@mandatory_fields) {
192
            push(@missing_fields, $mandatory_field) if (not exists $body->{$mandatory_field});
193
        }
194
195
        if ( @missing_fields ) {
196
            return $c->$cb({error => 'Missing mandatory fields: ' . join(', ', @missing_fields)}, 400);
197
        }
198
    }
199
186
200
    # Is suggester anonymous?
187
    # Is suggester anonymous?
201
    my $is_anonymous = not (defined $body->{suggestedby} and
188
    my $is_anonymous = not (defined $body->{suggestedby} and
Lines 204-210 sub _validate_body { Link Here
204
191
205
    # Refuse if are anonymous suggestions disabled
192
    # Refuse if are anonymous suggestions disabled
206
    if ( $is_anonymous ) {
193
    if ( $is_anonymous ) {
207
        return $c->$cb({error => 'Anonymous suggestions are disabled'}, 403)
194
        return $c->render( status => 403, openapi => {error => 'Anonymous suggestions are disabled'} )
208
        unless C4::Context->preference('AnonSuggestions');
195
        unless C4::Context->preference('AnonSuggestions');
209
    }
196
    }
210
197
Lines 213-259 sub _validate_body { Link Here
213
    if ( $max_open_suggestions gt 0 and not $is_anonymous ) {
200
    if ( $max_open_suggestions gt 0 and not $is_anonymous ) {
214
        my $count = Koha::Suggestions->search({suggestedby => $body->{suggestedby}})->count();
201
        my $count = Koha::Suggestions->search({suggestedby => $body->{suggestedby}})->count();
215
202
216
        return $c->$cb({error =>
203
        return $c->render( status => 403 , openapi => {error =>
217
                'You have ' . $count . ' opened suggestions out of ' . $max_open_suggestions}, 403)
204
                'You have ' . $count . ' opened suggestions out of ' . $max_open_suggestions} )
218
        if ( $count >= $max_open_suggestions );
205
        if ( $count >= $max_open_suggestions );
219
    }
206
    }
220
207
221
    # Check STATUS is valid
208
    # Check STATUS is valid
222
    if ( exists $body->{STATUS} ) {
209
    if ( exists $body->{STATUS} ) {
223
        return $c->$cb({error => 'STATUS must be one of ASKED, CHECKED, ACCEPTED, or REJECTED'}, 400)
210
        return $c->render( status => 400, openapi => {error => 'STATUS must be one of ASKED, CHECKED, ACCEPTED, or REJECTED'} )
224
        unless ($body->{STATUS} =~ m/^(ASKED|CHECKED|ACCEPTED|REJECTED)$/);
211
        unless ($body->{STATUS} =~ m/^(ASKED|CHECKED|ACCEPTED|REJECTED)$/);
225
    }
212
    }
226
213
227
    # Check itemtype is valid
214
    # Check itemtype is valid
228
    if ( exists $body->{itemtype} ) {
215
    if ( exists $body->{itemtype} ) {
229
        my @item_types = map {$_->unblessed->{itemtype}} Koha::ItemTypes->search;
216
        my @item_types = map {$_->unblessed->{itemtype}} Koha::ItemTypes->search;
230
        return $c->$cb({error => 'itemtype must be one of ' . join(', ', @item_types)}, 400)
217
        return $c->render( status => 400 , openapi => {error => 'itemtype must be one of ' . join(', ', @item_types)} )
231
        unless /^$body->{itemtype}$/ ~~ @item_types;
218
        unless /^$body->{itemtype}$/ ~~ @item_types;
232
    }
219
    }
233
220
234
    # Check branchcode is valid
221
    # Check branchcode is valid
235
    if ( exists $body->{branchcode} ) {
222
    if ( exists $body->{branchcode} ) {
236
        my @branch_codes = map {$_->unblessed->{branchcode}} Koha::Libraries->search;
223
        my @branch_codes = map {$_->unblessed->{branchcode}} Koha::Libraries->search;
237
        return $c->$cb({error => 'branchcode must be one of ' . join(', ', @branch_codes)}, 400)
224
        return $c->render( status => 400 , openapi => {error => 'branchcode must be one of ' . join(', ', @branch_codes)} )
238
        unless /^$body->{branchcode}$/ ~~ @branch_codes;
225
        unless /^$body->{branchcode}$/ ~~ @branch_codes;
239
    }
226
    }
240
227
241
    # Check patron reason is valid
228
    # Check patron reason is valid
242
    if ( exists $body->{patronreason} ) {
229
    if ( exists $body->{patronreason} ) {
243
        my @authorized_values = map { $_->{authorised_value} } @{ C4::Koha::GetAuthorisedValues('OPAC_SUG') };
230
        my @authorized_values = map { $_->{authorised_value} } @{ C4::Koha::GetAuthorisedValues('OPAC_SUG') };
244
        return $c->$cb({error => 'patronreason must be one of ' . join(', ', @authorized_values)}, 400)
231
        return $c->render( status => 400, openapi => {error => 'patronreason must be one of ' . join(', ', @authorized_values)} )
245
        unless /^$body->{patronreason}$/ ~~ @authorized_values;
232
        unless /^$body->{patronreason}$/ ~~ @authorized_values;
246
    }
233
    }
247
234
248
    # Check suggestedby patron exists
235
    # Check suggestedby patron exists
249
    if ( exists $body->{suggestedby} ) {
236
    if ( exists $body->{suggestedby} ) {
250
        return $c->$cb({error => 'suggestedby patron not found'}, 400)
237
        return $c->render( status => 400 , openapi => {error => 'suggestedby patron not found'} )
251
        unless Koha::Patrons->find($body->{suggestedby});
238
        unless Koha::Patrons->find($body->{suggestedby});
252
    }
239
    }
253
240
254
    # Check managedby patron exists
241
    # Check managedby patron exists
255
    if ( exists $body->{managedby} ) {
242
    if ( exists $body->{managedby} ) {
256
        return $c->$cb({error => 'managedby patron not found'}, 400)
243
        return $c->render( status => 400 , openapi => {error => 'managedby patron not found'} )
257
        unless Koha::Patrons->find($body->{managedby});
244
        unless Koha::Patrons->find($body->{managedby});
258
    }
245
    }
259
246
(-)a/api/v1/swagger/definitions/suggestion.json (-4 / +4 lines)
Lines 7-13 Link Here
7
    },
7
    },
8
    "suggestedby": {
8
    "suggestedby": {
9
      "type": "string",
9
      "type": "string",
10
      "description": "borrowernumber for the person making the suggestion, foreign key linking to the borrowers table"
10
      "description": "patron_id for the person making the suggestion, foreign key linking to the borrowers table"
11
    },
11
    },
12
    "suggesteddate": {
12
    "suggesteddate": {
13
      "type": "string",
13
      "type": "string",
Lines 15-21 Link Here
15
    },
15
    },
16
    "managedby": {
16
    "managedby": {
17
      "type": ["string", "null"],
17
      "type": ["string", "null"],
18
      "description": "borrowernumber for the librarian managing the suggestion, foreign key linking to the borrowers table"
18
      "description": "patron_id for the librarian managing the suggestion, foreign key linking to the borrowers table"
19
    },
19
    },
20
    "manageddate": {
20
    "manageddate": {
21
      "type": ["string", "null"],
21
      "type": ["string", "null"],
Lines 23-29 Link Here
23
    },
23
    },
24
    "acceptedby": {
24
    "acceptedby": {
25
      "type": ["string", "null"],
25
      "type": ["string", "null"],
26
      "description": "borrowernumber for the librarian who accepted the suggestion, foreign key linking to the borrowers table"
26
      "description": "patron_id for the librarian who accepted the suggestion, foreign key linking to the borrowers table"
27
    },
27
    },
28
    "accepteddate": {
28
    "accepteddate": {
29
      "type": ["string", "null"],
29
      "type": ["string", "null"],
Lines 31-37 Link Here
31
    },
31
    },
32
    "rejectedby": {
32
    "rejectedby": {
33
      "type": ["string", "null"],
33
      "type": ["string", "null"],
34
      "description": "borrowernumber for the librarian who rejected the suggestion, foreign key linking to the borrowers table"
34
      "description": "patron_id for the librarian who rejected the suggestion, foreign key linking to the borrowers table"
35
    },
35
    },
36
    "rejecteddate": {
36
    "rejecteddate": {
37
      "type": ["string", "null"],
37
      "type": ["string", "null"],
(-)a/api/v1/swagger/paths/suggestions.json (-11 / +10 lines)
Lines 1-8 Link Here
1
{
1
{
2
  "/suggestions": {
2
  "/suggestions": {
3
    "get": {
3
    "get": {
4
      "x-mojo-controller": "Koha::REST::V1::Suggestions",
4
      "x-mojo-to": "Suggestions#list",
5
      "operationId": "list",
5
      "operationId" : "list",
6
      "tags": ["patrons", "suggestions"],
6
      "tags": ["patrons", "suggestions"],
7
      "parameters": [
7
      "parameters": [
8
        {
8
        {
Lines 15-39 Link Here
15
          "name": "suggestedby",
15
          "name": "suggestedby",
16
          "in": "query",
16
          "in": "query",
17
          "type": "integer",
17
          "type": "integer",
18
          "description": "borrowernumber for the person making the suggestion, foreign key linking to the borrowers table"
18
          "description": "patron_id for the person making the suggestion, foreign key linking to the borrowers table"
19
        },
19
        },
20
        {
20
        {
21
          "name": "managedby",
21
          "name": "managedby",
22
          "in": "query",
22
          "in": "query",
23
          "type": "integer",
23
          "type": "integer",
24
          "description": "borrowernumber for the librarian managing the suggestion, foreign key linking to the borrowers table"
24
          "description": "patron_id for the librarian managing the suggestion, foreign key linking to the borrowers table"
25
        },
25
        },
26
        {
26
        {
27
          "name": "acceptedby",
27
          "name": "acceptedby",
28
          "in": "query",
28
          "in": "query",
29
          "type": "integer",
29
          "type": "integer",
30
          "description": "borrowernumber for the librarian who accepted the suggestion, foreign key linking to the borrowers table"
30
          "description": "patron_id for the librarian who accepted the suggestion, foreign key linking to the borrowers table"
31
        },
31
        },
32
        {
32
        {
33
          "name": "rejectedby",
33
          "name": "rejectedby",
34
          "in": "query",
34
          "in": "query",
35
          "type": "integer",
35
          "type": "integer",
36
          "description": "borrowernumber for the librarian who rejected the suggestion, foreign key linking to the borrowers table"
36
          "description": "patron_id for the librarian who rejected the suggestion, foreign key linking to the borrowers table"
37
        },
37
        },
38
        {
38
        {
39
          "name": "STATUS",
39
          "name": "STATUS",
Lines 118-124 Link Here
118
      }
118
      }
119
    },
119
    },
120
    "post": {
120
    "post": {
121
      "x-mojo-controller": "Koha::REST::V1::Suggestions",
121
      "x-mojo-to": "Suggestions#add",
122
      "operationId": "add",
122
      "operationId": "add",
123
      "tags": ["patrons", "suggestions"],
123
      "tags": ["patrons", "suggestions"],
124
      "parameters": [{
124
      "parameters": [{
Lines 169-175 Link Here
169
  },
169
  },
170
  "/suggestions/{suggestionid}": {
170
  "/suggestions/{suggestionid}": {
171
    "get": {
171
    "get": {
172
      "x-mojo-controller": "Koha::REST::V1::Suggestions",
172
      "x-mojo-to": "Suggestions#get",
173
      "operationId": "get",
173
      "operationId": "get",
174
      "tags": ["patrons", "suggestions"],
174
      "tags": ["patrons", "suggestions"],
175
      "parameters": [{
175
      "parameters": [{
Lines 208-214 Link Here
208
      }
208
      }
209
    },
209
    },
210
    "put": {
210
    "put": {
211
      "x-mojo-controller": "Koha::REST::V1::Suggestions",
211
      "x-mojo-to": "Suggestions#update",
212
      "operationId": "update",
212
      "operationId": "update",
213
      "tags": ["patrons", "suggestions"],
213
      "tags": ["patrons", "suggestions"],
214
      "parameters": [{
214
      "parameters": [{
Lines 265-271 Link Here
265
      }
265
      }
266
    },
266
    },
267
    "delete": {
267
    "delete": {
268
      "x-mojo-controller": "Koha::REST::V1::Suggestions",
268
      "x-mojo-to": "Suggestions#delete",
269
      "operationId": "delete",
269
      "operationId": "delete",
270
      "tags": ["patrons", "suggestions"],
270
      "tags": ["patrons", "suggestions"],
271
      "parameters": [{
271
      "parameters": [{
272
- 

Return to bug 17314