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

(-)a/Koha/REST/V1/Holds.pm (+83 lines)
Lines 555-559 sub update_pickup_location { Link Here
555
    };
555
    };
556
}
556
}
557
557
558
=head3 update_hold_date
559
560
Method that handles modifying the hold date of a Koha::Hold object
561
562
=cut
563
564
sub update_hold_date {
565
    my $c = shift->openapi->valid_input or return;
566
567
    my $hold_id = $c->validation->param('hold_id');
568
    my $body    = $c->validation->param('body');
569
    my $hold_date = $body->{hold_date};
570
571
    my $hold = Koha::Holds->find($hold_id);
572
573
    unless (C4::Context->preference('AllowHoldDateInFuture')) {
574
        return $c->render(
575
            status  => 403,
576
            openapi => { error => "Update not allowed" }
577
        );
578
    }
579
580
    unless ($hold) {
581
        return $c->render(
582
            status  => 404,
583
            openapi => { error => "Hold not found" }
584
        );
585
    }
586
587
    return try {
588
589
        $hold->set({reservedate => $hold_date})->store;
590
591
        return $c->render(
592
            status  => 200,
593
            openapi => {
594
                hold_date => $hold_date
595
            }
596
        );
597
    }
598
    catch {
599
        $c->unhandled_exception($_);
600
    };
601
}
602
603
=head3 update_expiration_date
604
605
Method that handles modifying the expiration date of a Koha::Hold object
606
607
=cut
608
609
sub update_expiration_date {
610
    my $c = shift->openapi->valid_input or return;
611
612
    my $hold_id = $c->validation->param('hold_id');
613
    my $body    = $c->validation->param('body');
614
    my $expiration_date = $body->{expiration_date};
615
616
    my $hold = Koha::Holds->find($hold_id);
617
618
    unless ($hold) {
619
        return $c->render(
620
            status  => 404,
621
            openapi => { error => "Hold not found" }
622
        );
623
    }
624
625
    return try {
626
627
        $hold->set({expirationdate => $expiration_date})->store;
628
629
        return $c->render(
630
            status  => 200,
631
            openapi => {
632
                expiration_date => $expiration_date
633
            }
634
        );
635
    }
636
    catch {
637
        $c->unhandled_exception($_);
638
    };
639
}
640
558
641
559
1;
642
1;
(-)a/api/v1/swagger/paths/holds.yaml (+136 lines)
Lines 695-697 Link Here
695
    x-koha-authorization:
695
    x-koha-authorization:
696
      permissions:
696
      permissions:
697
        reserveforothers: place_holds
697
        reserveforothers: place_holds
698
"/holds/{hold_id}/hold_date":
699
  put:
700
    x-mojo-to: Holds#update_hold_date
701
    operationId: updateHoldDate
702
    tags:
703
      - holds
704
    summary: Update hold date for the hold
705
    description: Set an hold date for the hold
706
    parameters:
707
      - $ref: ../parameters.yaml#/hold_id_pp
708
      - name: body
709
        in: body
710
        description: Hold date
711
        required: true
712
        schema:
713
          type: object
714
          properties:
715
            hold_date:
716
              type: 
717
                - string
718
                - 'null'
719
              description: Hold date
720
          additionalProperties: false
721
    produces:
722
      - application/json
723
    responses:
724
      "200":
725
        description: The hold date value for the hold
726
        schema:
727
          type: object
728
          properties:
729
            hold_date:
730
              type: 
731
                - string
732
                - 'null'
733
              description: The hold date
734
          additionalProperties: false
735
      "400":
736
        description: Missing or wrong parameters
737
        schema:
738
          $ref: ../definitions.yaml#/error
739
      "401":
740
        description: Authentication required
741
        schema:
742
          $ref: ../definitions.yaml#/error
743
      "403":
744
        description: Access forbidden
745
        schema:
746
          $ref: ../definitions.yaml#/error
747
      "404":
748
        description: Hold not found
749
        schema:
750
          $ref: ../definitions.yaml#/error
751
      "409":
752
        description: Unable to perform action on hold
753
        schema:
754
          $ref: ../definitions.yaml#/error
755
      "500":
756
        description: Internal error
757
        schema:
758
          $ref: ../definitions.yaml#/error
759
      "503":
760
        description: Under maintenance
761
        schema:
762
          $ref: ../definitions.yaml#/error
763
    x-koha-authorization:
764
      permissions:
765
        reserveforothers: place_holds
766
"/holds/{hold_id}/expiration_date":
767
  put:
768
    x-mojo-to: Holds#update_expiration_date
769
    operationId: updateHoldExpirationDate
770
    tags:
771
      - holds
772
    summary: Update expiration date for the hold
773
    description: Set an expiration date for the hold
774
    parameters:
775
      - $ref: ../parameters.yaml#/hold_id_pp
776
      - name: body
777
        in: body
778
        description: Expiration date
779
        required: true
780
        schema:
781
          type: object
782
          properties:
783
            expiration_date:
784
              type: 
785
                - string
786
                - 'null'
787
              description: Expiration date
788
          additionalProperties: false
789
    produces:
790
      - application/json
791
    responses:
792
      "200":
793
        description: The expiration date value for the hold
794
        schema:
795
          type: object
796
          properties:
797
            expiration_date:
798
              type: 
799
                - string
800
                - 'null'
801
              description: The expiration date
802
          additionalProperties: false
803
      "400":
804
        description: Missing or wrong parameters
805
        schema:
806
          $ref: ../definitions.yaml#/error
807
      "401":
808
        description: Authentication required
809
        schema:
810
          $ref: ../definitions.yaml#/error
811
      "403":
812
        description: Access forbidden
813
        schema:
814
          $ref: ../definitions.yaml#/error
815
      "404":
816
        description: Hold not found
817
        schema:
818
          $ref: ../definitions.yaml#/error
819
      "409":
820
        description: Unable to perform action on hold
821
        schema:
822
          $ref: ../definitions.yaml#/error
823
      "500":
824
        description: Internal error
825
        schema:
826
          $ref: ../definitions.yaml#/error
827
      "503":
828
        description: Under maintenance
829
        schema:
830
          $ref: ../definitions.yaml#/error
831
    x-koha-authorization:
832
      permissions:
833
        reserveforothers: place_holds
(-)a/api/v1/swagger/swagger.yaml (+4 lines)
Lines 157-162 paths: Link Here
157
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1priority"
157
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1priority"
158
  "/holds/{hold_id}/suspension":
158
  "/holds/{hold_id}/suspension":
159
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1suspension"
159
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1suspension"
160
  "/holds/{hold_id}/hold_date":
161
    $ref: ./paths/holds.yaml#/~1holds~1{hold_id}~1hold_date
162
  "/holds/{hold_id}/expiration_date":
163
    $ref: ./paths/holds.yaml#/~1holds~1{hold_id}~1expiration_date
160
  /ill_backends:
164
  /ill_backends:
161
    $ref: ./paths/ill_backends.yaml#/~1ill_backends
165
    $ref: ./paths/ill_backends.yaml#/~1ill_backends
162
  "/ill_backends/{ill_backend_id}":
166
  "/ill_backends/{ill_backend_id}":
(-)a/t/db_dependent/api/v1/holds.t (-2 / +138 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 14;
20
use Test::More tests => 16;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Mojo;
22
use Test::Mojo;
23
use t::lib::TestBuilder;
23
use t::lib::TestBuilder;
Lines 1461-1463 subtest 'delete() tests' => sub { Link Here
1461
1461
1462
    $schema->storage->txn_rollback;
1462
    $schema->storage->txn_rollback;
1463
};
1463
};
1464
- 
1464
1465
subtest 'PUT /holds/{hold_id}/hold_date tests' => sub {
1466
1467
    plan tests => 10;
1468
1469
    $schema->storage->txn_begin;
1470
1471
    my $password = 'AbcdEFG123';
1472
1473
    my $library_1 = $builder->build_object(
1474
        { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
1475
1476
    my $patron = $builder->build_object(
1477
        { class => 'Koha::Patrons', value => { flags => 0 } } );
1478
    $patron->set_password( { password => $password, skip_validation => 1 } );
1479
    my $userid = $patron->userid;
1480
    $builder->build(
1481
        {
1482
            source => 'UserPermission',
1483
            value  => {
1484
                borrowernumber => $patron->borrowernumber,
1485
                module_bit     => 6,
1486
                code           => 'place_holds',
1487
            },
1488
        }
1489
    );
1490
1491
    # Disable logging
1492
    t::lib::Mocks::mock_preference( 'HoldsLog',      0 );
1493
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
1494
1495
    my $biblio = $builder->build_sample_biblio;
1496
1497
    # biblio-level hold
1498
    my $hold = Koha::Holds->find(
1499
        AddReserve(
1500
            {
1501
                branchcode     => $library_1->branchcode,
1502
                borrowernumber => $patron->borrowernumber,
1503
                biblionumber   => $biblio->biblionumber,
1504
                priority       => 1,
1505
                itemnumber     => undef,
1506
            }
1507
        )
1508
    );
1509
1510
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 0 );
1511
1512
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1513
          . $hold->id
1514
          . "/hold_date" => json => { hold_date => '2022-01-01' } )
1515
      ->status_is(403)
1516
      ->json_is({ error => 'Update not allowed' });
1517
1518
    
1519
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 );
1520
1521
    # Attempt to use an invalid pickup locations ends in 400
1522
    $t->put_ok( "//$userid:$password@/api/v1/holds/0"
1523
          . "/hold_date" => json => { hold_date => '2022-01-01' } )
1524
      ->status_is(404)
1525
      ->json_is({ error => 'Hold not found' });
1526
1527
1528
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1529
          . $hold->id
1530
          . "/hold_date" => json => { hold_date => '2022-01-01' } )
1531
      ->status_is(200)
1532
      ->json_is({ hold_date => '2022-01-01' });
1533
1534
    is( $hold->discard_changes->reservedate, '2022-01-01', 'hold date changed correctly' );
1535
1536
    $schema->storage->txn_rollback;
1537
};
1538
1539
subtest 'PUT /holds/{hold_id}/expiration_date tests' => sub {
1540
1541
    plan tests => 7;
1542
1543
    $schema->storage->txn_begin;
1544
1545
    my $password = 'AbcdEFG123';
1546
1547
    my $library_1 = $builder->build_object(
1548
        { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
1549
1550
    my $patron = $builder->build_object(
1551
        { class => 'Koha::Patrons', value => { flags => 0 } } );
1552
    $patron->set_password( { password => $password, skip_validation => 1 } );
1553
    my $userid = $patron->userid;
1554
    $builder->build(
1555
        {
1556
            source => 'UserPermission',
1557
            value  => {
1558
                borrowernumber => $patron->borrowernumber,
1559
                module_bit     => 6,
1560
                code           => 'place_holds',
1561
            },
1562
        }
1563
    );
1564
1565
    # Disable logging
1566
    t::lib::Mocks::mock_preference( 'HoldsLog',      0 );
1567
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
1568
1569
    my $biblio = $builder->build_sample_biblio;
1570
1571
    # biblio-level hold
1572
    my $hold = Koha::Holds->find(
1573
        AddReserve(
1574
            {
1575
                branchcode     => $library_1->branchcode,
1576
                borrowernumber => $patron->borrowernumber,
1577
                biblionumber   => $biblio->biblionumber,
1578
                priority       => 1,
1579
                itemnumber     => undef,
1580
            }
1581
        )
1582
    );
1583
1584
    # Attempt to use an invalid pickup locations ends in 400
1585
    $t->put_ok( "//$userid:$password@/api/v1/holds/0"
1586
          . "/expiration_date" => json => { expiration_date => '2022-01-01' } )
1587
      ->status_is(404)
1588
      ->json_is({ error => 'Hold not found' });
1589
1590
1591
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1592
          . $hold->id
1593
          . "/expiration_date" => json => { expiration_date => '2022-01-01' } )
1594
      ->status_is(200)
1595
      ->json_is({ expiration_date => '2022-01-01' });
1596
1597
    is( $hold->discard_changes->expirationdate, '2022-01-01', 'expiration date changed correctly' );
1598
1599
    $schema->storage->txn_rollback;
1600
};

Return to bug 30661