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

(-)a/Koha/REST/V1/Holds.pm (+77 lines)
Lines 560-563 sub update_pickup_location { Link Here
560
    };
560
    };
561
}
561
}
562
562
563
=head3 update_hold_date
564
565
Method that handles modifying the hold date of a Koha::Hold object
566
567
=cut
568
569
sub update_hold_date {
570
    my $c = shift->openapi->valid_input or return;
571
572
    my $hold_id   = $c->param('hold_id');
573
    my $body      = $c->req->json;
574
    my $hold_date = $body->{hold_date};
575
576
    my $hold = Koha::Holds->find($hold_id);
577
578
    unless ( C4::Context->preference('AllowHoldDateInFuture') ) {
579
        return $c->render(
580
            status  => 403,
581
            openapi => { error => "Update not allowed" }
582
        );
583
    }
584
585
    unless ($hold) {
586
        return $c->render(
587
            status  => 404,
588
            openapi => { error => "Hold not found" }
589
        );
590
    }
591
592
    return try {
593
594
        $hold->set( { reservedate => $hold_date } )->store;
595
596
        return $c->render(
597
            status  => 200,
598
            openapi => { hold_date => $hold_date }
599
        );
600
    } catch {
601
        $c->unhandled_exception($_);
602
    };
603
}
604
605
=head3 update_expiration_date
606
607
Method that handles modifying the expiration date of a Koha::Hold object
608
609
=cut
610
611
sub update_expiration_date {
612
    my $c = shift->openapi->valid_input or return;
613
614
    my $hold_id         = $c->param('hold_id');
615
    my $body            = $c->req->json;
616
    my $expiration_date = $body->{expiration_date};
617
618
    my $hold = Koha::Holds->find($hold_id);
619
620
    unless ($hold) {
621
        return $c->render(
622
            status  => 404,
623
            openapi => { error => "Hold not found" }
624
        );
625
    }
626
627
    return try {
628
629
        $hold->set( { expirationdate => $expiration_date } )->store;
630
631
        return $c->render(
632
            status  => 200,
633
            openapi => { expiration_date => $expiration_date }
634
        );
635
    } catch {
636
        $c->unhandled_exception($_);
637
    };
638
}
639
563
1;
640
1;
(-)a/api/v1/swagger/paths/holds.yaml (+142 lines)
Lines 755-757 Link Here
755
    x-koha-authorization:
755
    x-koha-authorization:
756
      permissions:
756
      permissions:
757
        reserveforothers: place_holds
757
        reserveforothers: place_holds
758
"/holds/{hold_id}/hold_date":
759
  put:
760
    x-mojo-to: Holds#update_hold_date
761
    operationId: updateHoldDate
762
    tags:
763
      - holds
764
    summary: Update hold date
765
    parameters:
766
      - $ref: "../swagger.yaml#/parameters/hold_id_pp"
767
      - name: body
768
        in: body
769
        description: A JSON object containing the new hold date
770
        required: true
771
        schema:
772
          type: object
773
          properties:
774
            hold_date:
775
              description: The date the hold was placed
776
              type: string
777
              format: date
778
          additionalProperties: false
779
    produces:
780
      - application/json
781
    responses:
782
      "200":
783
        description: The new hold date value for the hold
784
        schema:
785
          type: object
786
          properties:
787
            hold_date:
788
              description: The date the hold was placed
789
              type: string
790
              format: date
791
          additionalProperties: false
792
      "400":
793
        description: Bad request
794
        schema:
795
          $ref: "../swagger.yaml#/definitions/error"
796
      "401":
797
        description: Authentication required
798
        schema:
799
          $ref: "../swagger.yaml#/definitions/error"
800
      "403":
801
        description: Access forbidden
802
        schema:
803
          $ref: "../swagger.yaml#/definitions/error"
804
      "404":
805
        description: Hold not found
806
        schema:
807
          $ref: "../swagger.yaml#/definitions/error"
808
      "409":
809
        description: |
810
          Unable to perform action on hold. Possible `error_code` attribute values:
811
812
          * `hold_waiting`
813
          * `hold_in_transit`
814
          * `hold_in_processing`
815
        schema:
816
          $ref: "../swagger.yaml#/definitions/error"
817
      "500":
818
        description: |
819
          Internal server error. Possible `error_code` attribute values:
820
821
          * `internal_server_error`
822
      "503":
823
        description: Under maintenance
824
        schema:
825
          $ref: "../swagger.yaml#/definitions/error"
826
    x-koha-authorization:
827
      permissions:
828
        reserveforothers: place_holds
829
"/holds/{hold_id}/expiration_date":
830
  put:
831
    x-mojo-to: Holds#update_expiration_date
832
    operationId: updateHoldExpirationDate
833
    tags:
834
      - holds
835
    summary: Update hold expiration date
836
    parameters:
837
      - $ref: "../swagger.yaml#/parameters/hold_id_pp"
838
      - name: body
839
        in: body
840
        description: A JSON object containing the new expiration date
841
        required: true
842
        schema:
843
          type: object
844
          properties:
845
            expiration_date:
846
              description: The date the hold expires
847
              type: string
848
              format: date
849
          additionalProperties: false
850
    produces:
851
      - application/json
852
    responses:
853
      "200":
854
        description: The new expiration date value for the hold
855
        schema:
856
          type: object
857
          properties:
858
            expiration_date:
859
              description: The date the hold expires
860
              type: string
861
              format: date
862
          additionalProperties: false
863
      "400":
864
        description: Bad request
865
        schema:
866
          $ref: "../swagger.yaml#/definitions/error"
867
      "401":
868
        description: Authentication required
869
        schema:
870
          $ref: "../swagger.yaml#/definitions/error"
871
      "403":
872
        description: Access forbidden
873
        schema:
874
          $ref: "../swagger.yaml#/definitions/error"
875
      "404":
876
        description: Hold not found
877
        schema:
878
          $ref: "../swagger.yaml#/definitions/error"
879
      "409":
880
        description: |
881
          Unable to perform action on hold. Possible `error_code` attribute values:
882
883
          * `hold_waiting`
884
          * `hold_in_transit`
885
          * `hold_in_processing`
886
        schema:
887
          $ref: "../swagger.yaml#/definitions/error"
888
      "500":
889
        description: |
890
          Internal server error. Possible `error_code` attribute values:
891
892
          * `internal_server_error`
893
      "503":
894
        description: Under maintenance
895
        schema:
896
          $ref: "../swagger.yaml#/definitions/error"
897
    x-koha-authorization:
898
      permissions:
899
        reserveforothers: place_holds
(-)a/api/v1/swagger/swagger.yaml (+4 lines)
Lines 391-396 paths: Link Here
391
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1priority"
391
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1priority"
392
  "/holds/{hold_id}/suspension":
392
  "/holds/{hold_id}/suspension":
393
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1suspension"
393
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1suspension"
394
  "/holds/{hold_id}/hold_date":
395
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1hold_date"
396
  "/holds/{hold_id}/expiration_date":
397
    $ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1expiration_date"
394
  /ill/backends:
398
  /ill/backends:
395
    $ref: ./paths/ill_backends.yaml#/~1ill~1backends
399
    $ref: ./paths/ill_backends.yaml#/~1ill~1backends
396
  "/ill/backends/{ill_backend_id}":
400
  "/ill/backends/{ill_backend_id}":
(-)a/t/db_dependent/api/v1/holds.t (-2 / +123 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 1575-1577 subtest 'delete() tests' => sub { Link Here
1575
1575
1576
    $schema->storage->txn_rollback;
1576
    $schema->storage->txn_rollback;
1577
};
1577
};
1578
- 
1578
1579
subtest 'PUT /holds/{hold_id}/hold_date tests' => sub {
1580
1581
    plan tests => 10;
1582
1583
    $schema->storage->txn_begin;
1584
1585
    my $password = 'AbcdEFG123';
1586
1587
    my $library_1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
1588
1589
    my $patron = $builder->build_object( { class => 'Koha::Patrons', value => { flags => 0 } } );
1590
    $patron->set_password( { password => $password, skip_validation => 1 } );
1591
    my $userid = $patron->userid;
1592
    $builder->build(
1593
        {
1594
            source => 'UserPermission',
1595
            value  => {
1596
                borrowernumber => $patron->borrowernumber,
1597
                module_bit     => 6,
1598
                code           => 'place_holds',
1599
            },
1600
        }
1601
    );
1602
1603
    # Disable logging
1604
    t::lib::Mocks::mock_preference( 'HoldsLog',      0 );
1605
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
1606
1607
    my $biblio = $builder->build_sample_biblio;
1608
1609
    # biblio-level hold
1610
    my $hold = Koha::Holds->find(
1611
        AddReserve(
1612
            {
1613
                branchcode     => $library_1->branchcode,
1614
                borrowernumber => $patron->borrowernumber,
1615
                biblionumber   => $biblio->biblionumber,
1616
                priority       => 1,
1617
                itemnumber     => undef,
1618
            }
1619
        )
1620
    );
1621
1622
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 0 );
1623
1624
    $t->put_ok(
1625
        "//$userid:$password@/api/v1/holds/" . $hold->id . "/hold_date" => json => { hold_date => '2022-01-01' } )
1626
        ->status_is(403)->json_is( { error => 'Update not allowed' } );
1627
1628
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 );
1629
1630
    # Attempt to use an invalid pickup locations ends in 400
1631
    $t->put_ok( "//$userid:$password@/api/v1/holds/0" . "/hold_date" => json => { hold_date => '2022-01-01' } )
1632
        ->status_is(404)->json_is( { error => 'Hold not found' } );
1633
1634
    $t->put_ok(
1635
        "//$userid:$password@/api/v1/holds/" . $hold->id . "/hold_date" => json => { hold_date => '2022-01-01' } )
1636
        ->status_is(200)->json_is( { hold_date => '2022-01-01' } );
1637
1638
    is( $hold->discard_changes->reservedate, '2022-01-01', 'hold date changed correctly' );
1639
1640
    $schema->storage->txn_rollback;
1641
};
1642
1643
subtest 'PUT /holds/{hold_id}/expiration_date tests' => sub {
1644
1645
    plan tests => 7;
1646
1647
    $schema->storage->txn_begin;
1648
1649
    my $password = 'AbcdEFG123';
1650
1651
    my $library_1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
1652
1653
    my $patron = $builder->build_object( { class => 'Koha::Patrons', value => { flags => 0 } } );
1654
    $patron->set_password( { password => $password, skip_validation => 1 } );
1655
    my $userid = $patron->userid;
1656
    $builder->build(
1657
        {
1658
            source => 'UserPermission',
1659
            value  => {
1660
                borrowernumber => $patron->borrowernumber,
1661
                module_bit     => 6,
1662
                code           => 'place_holds',
1663
            },
1664
        }
1665
    );
1666
1667
    # Disable logging
1668
    t::lib::Mocks::mock_preference( 'HoldsLog',      0 );
1669
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
1670
1671
    my $biblio = $builder->build_sample_biblio;
1672
1673
    # biblio-level hold
1674
    my $hold = Koha::Holds->find(
1675
        AddReserve(
1676
            {
1677
                branchcode     => $library_1->branchcode,
1678
                borrowernumber => $patron->borrowernumber,
1679
                biblionumber   => $biblio->biblionumber,
1680
                priority       => 1,
1681
                itemnumber     => undef,
1682
            }
1683
        )
1684
    );
1685
1686
    # Attempt to use an invalid pickup locations ends in 400
1687
    $t->put_ok(
1688
        "//$userid:$password@/api/v1/holds/0" . "/expiration_date" => json => { expiration_date => '2022-01-01' } )
1689
        ->status_is(404)->json_is( { error => 'Hold not found' } );
1690
1691
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1692
            . $hold->id
1693
            . "/expiration_date" => json => { expiration_date => '2022-01-01' } )->status_is(200)
1694
        ->json_is( { expiration_date => '2022-01-01' } );
1695
1696
    is( $hold->discard_changes->expirationdate, '2022-01-01', 'expiration date changed correctly' );
1697
1698
    $schema->storage->txn_rollback;
1699
};

Return to bug 30661