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

(-)a/Koha/REST/V1/Patrons/Attributes.pm (-2 / +76 lines)
Lines 186-192 sub overwrite { Link Here
186
                    status  => 400,
186
                    status  => 400,
187
                    openapi => { error => "$_" }
187
                    openapi => { error => "$_" }
188
                );
188
                );
189
190
            }
189
            }
191
            elsif (
190
            elsif (
192
                $_->isa(
191
                $_->isa(
Lines 222-230 sub overwrite { Link Here
222
    };
221
    };
223
}
222
}
224
223
224
225
=head3 update
226
227
Controller method that handles updating a single extended patron attribute.
228
229
=cut
230
231
sub update {
232
    my $c = shift->openapi->valid_input or return;
233
234
    my $patron = Koha::Patrons->find( $c->validation->param('patron_id') );
235
236
    unless ($patron) {
237
        return $c->render(
238
            status  => 404,
239
            openapi => {
240
                error => 'Patron not found'
241
            }
242
        );
243
    }
244
245
    return try {
246
        my $attribute = $patron->extended_attributes->find(
247
            $c->validation->param('extended_attribute_id') );
248
249
        unless ($attribute) {
250
            return $c->render(
251
                status  => 404,
252
                openapi => {
253
                    error => 'Attribute not found'
254
                }
255
            );
256
        }
257
258
        $attribute->set_from_api( $c->validation->param('body') )->store;
259
        $attribute->discard_changes;
260
261
        return $c->render(
262
            status  => 200,
263
            openapi => $attribute->to_api
264
        );
265
    }
266
    catch {
267
        if ( blessed $_ ) {
268
            if ( $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType') ) {
269
                return $c->render(
270
                    status  => 400,
271
                    openapi => { error => "$_" }
272
                );
273
            }
274
            elsif (
275
                $_->isa(
276
                    'Koha::Exceptions::Patron::Attribute::UniqueIDConstraint')
277
              )
278
            {
279
                return $c->render(
280
                    status  => 409,
281
                    openapi => { error => "$_" }
282
                );
283
            }
284
            elsif (
285
                $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable') )
286
            {
287
                return $c->render(
288
                    status  => 409,
289
                    openapi => { error => "$_" }
290
                );
291
            }
292
        }
293
294
        $c->unhandled_exception($_);
295
    };
296
297
}
298
225
=head3 delete
299
=head3 delete
226
300
227
Controller method that handling removing an extended patron attribute
301
Controller method that handles removing an extended patron attribute.
228
302
229
=cut
303
=cut
230
304
(-)a/api/v1/swagger/paths/patrons_extended_attributes.json (+93 lines)
Lines 251-256 Link Here
251
    }
251
    }
252
  },
252
  },
253
  "/patrons/{patron_id}/extended_attributes/{extended_attribute_id}": {
253
  "/patrons/{patron_id}/extended_attributes/{extended_attribute_id}": {
254
    "patch": {
255
      "x-mojo-to": "Patrons::Attributes#update",
256
      "operationId": "updatePatronAttribute",
257
      "tags": [
258
        "patrons",
259
        "extended_attributes"
260
      ],
261
      "parameters": [
262
        {
263
          "$ref": "../parameters.json#/patron_id_pp"
264
        },
265
        {
266
          "name": "extended_attribute_id",
267
          "in": "path",
268
          "description": "Internal patron extended attribute identifier",
269
          "type": "integer",
270
          "required": true
271
        },
272
        {
273
          "name": "body",
274
          "in": "body",
275
          "description": "An object containing the updated values for the patron extended attribute",
276
          "required": true,
277
          "schema": {
278
            "type": "object",
279
            "properties": {
280
              "value": {
281
                "description": "Extended attribute value",
282
                "type": "string"
283
              }
284
            }
285
          }
286
        }
287
      ],
288
      "produces": [
289
        "application/json"
290
      ],
291
      "responses": {
292
        "200": {
293
          "description": "A successfully updated patron extended attribute",
294
          "schema": {
295
            "$ref": "../definitions.json#/patron_extended_attribute"
296
          }
297
        },
298
        "400": {
299
          "description": "Bad parameter",
300
          "schema": {
301
            "$ref": "../definitions.json#/error"
302
          }
303
        },
304
        "401": {
305
          "description": "Authentication required",
306
          "schema": {
307
            "$ref": "../definitions.json#/error"
308
          }
309
        },
310
        "403": {
311
          "description": "Access forbidden",
312
          "schema": {
313
            "$ref": "../definitions.json#/error"
314
          }
315
        },
316
        "404": {
317
          "description": "Object not found",
318
          "schema": {
319
            "$ref": "../definitions.json#/error"
320
          }
321
        },
322
        "409": {
323
          "description": "Conflict in updating resource",
324
          "schema": {
325
            "$ref": "../definitions.json#/error"
326
          }
327
        },
328
        "500": {
329
          "description": "Internal server error",
330
          "schema": {
331
            "$ref": "../definitions.json#/error"
332
          }
333
        },
334
        "503": {
335
          "description": "Under maintenance",
336
          "schema": {
337
            "$ref": "../definitions.json#/error"
338
          }
339
        }
340
      },
341
      "x-koha-authorization": {
342
        "permissions": {
343
          "borrowers": "edit_borrowers"
344
        }
345
      }
346
    },
254
    "delete": {
347
    "delete": {
255
      "x-mojo-to": "Patrons::Attributes#delete",
348
      "x-mojo-to": "Patrons::Attributes#delete",
256
      "operationId": "deletePatronAttribute",
349
      "operationId": "deletePatronAttribute",
(-)a/t/db_dependent/api/v1/patrons_extended_attributes.t (-2 / +115 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 4;
20
use Test::More tests => 5;
21
use Test::Mojo;
21
use Test::Mojo;
22
22
23
use t::lib::TestBuilder;
23
use t::lib::TestBuilder;
Lines 394-396 subtest 'delete() tests' => sub { Link Here
394
394
395
    $schema->storage->txn_rollback;
395
    $schema->storage->txn_rollback;
396
};
396
};
397
- 
397
398
subtest 'update() tests' => sub {
399
400
    plan tests => 12;
401
402
    $schema->storage->txn_begin;
403
404
    my $patron = $builder->build_object(
405
        {
406
            class => 'Koha::Patrons',
407
            value => { flags => 2**4 }    # 'borrowers' flag == 4
408
        }
409
    );
410
    my $password = 'thePassword123';
411
    $patron->set_password( { password => $password, skip_validation => 1 } );
412
    my $userid = $patron->userid;
413
414
    my $repeatable_attr_type = $builder->build_object(
415
        {
416
            class => 'Koha::Patron::Attribute::Types',
417
            value => {
418
                mandatory     => 0,
419
                repeatable    => 1,
420
                unique_id     => 0,
421
                category_code => undef
422
            }
423
        }
424
    );
425
    my $unique_attr_type = $builder->build_object(
426
        {
427
            class => 'Koha::Patron::Attribute::Types',
428
            value => {
429
                mandatory     => 0,
430
                repeatable    => 0,
431
                unique_id     => 1,
432
                category_code => undef
433
            }
434
        }
435
    );
436
437
    # Add a unique attribute to our patron
438
    my $unique_attribute = $patron->add_extended_attribute(
439
        {
440
            code      => $unique_attr_type->code,
441
            attribute => 'WOW'
442
        }
443
    );
444
445
    # Let's have an attribute ID we are sure doesn't exist on the DB
446
    my $non_existent_attribute = $patron->add_extended_attribute(
447
        {
448
            code      => $repeatable_attr_type->code,
449
            attribute => 'BOO'
450
        }
451
    );
452
    my $non_existent_attribute_id = $non_existent_attribute->id;
453
    $non_existent_attribute->delete;
454
455
    my $non_existent_patron =
456
      $builder->build_object( { class => 'Koha::Patrons' } );
457
    my $non_existent_patron_id = $non_existent_patron->id;
458
459
    # get rid of the patron
460
    $non_existent_patron->delete;
461
462
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
463
          . $non_existent_patron_id
464
          . '/extended_attributes/'
465
          . 123 => json => { value => 'something' } )->status_is(404)
466
      ->json_is( '/error' => 'Patron not found' );
467
468
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
469
          . $patron->id
470
          . '/extended_attributes/'
471
          . $non_existent_attribute_id => json => { value => 'something' } )
472
      ->status_is(404)->json_is( '/error' => 'Attribute not found' );
473
474
    my $response =
475
      $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
476
          . $patron->id
477
          . '/extended_attributes/'
478
          . $unique_attribute->id => json => { value => 'HEY' } )
479
      ->status_is(200)->tx->res->json;
480
481
    is_deeply(
482
        Koha::Patron::Attributes->find( $response->{extended_attribute_id} )
483
          ->to_api,
484
        $response,
485
        "The returned object is on the DB"
486
    );
487
488
    my $unique_value = 'HEHE';
489
490
    # Add a patron with the unique attribute to test changing to it
491
    $builder->build_object( { class => 'Koha::Patrons' } )
492
      ->add_extended_attribute(
493
        {
494
            code      => $unique_attr_type->code,
495
            attribute => $unique_value
496
        }
497
      );
498
499
    $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
500
          . $patron->id
501
          . '/extended_attributes/'
502
          . $unique_attribute->id => json => { value => $unique_value } )
503
      ->status_is(409)
504
      ->json_is( '/error' =>
505
            "Your action breaks a unique constraint on the attribute. type="
506
          . $unique_attr_type->code
507
          . " value=$unique_value" );
508
509
    $schema->storage->txn_rollback;
510
};

Return to bug 23666