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

(-)a/Koha/REST/V1/Biblios.pm (-1 / +64 lines)
Lines 22-28 use Mojo::Base 'Mojolicious::Controller'; Link Here
22
use Koha::Biblios;
22
use Koha::Biblios;
23
use Koha::Ratings;
23
use Koha::Ratings;
24
use Koha::RecordProcessor;
24
use Koha::RecordProcessor;
25
use C4::Biblio qw( DelBiblio );
25
use C4::Biblio qw( DelBiblio AddBiblio );
26
use C4::Search qw( FindDuplicate );
26
27
27
use List::MoreUtils qw( any );
28
use List::MoreUtils qw( any );
28
use MARC::Record::MiJ;
29
use MARC::Record::MiJ;
Lines 480-483 sub set_rating { Link Here
480
    };
481
    };
481
}
482
}
482
483
484
=head3 add
485
486
Controller function that handles creating a biblio object
487
488
=cut
489
490
sub add {
491
    my $c = shift->openapi->valid_input or return;
492
493
    try {
494
        my $body = $c->validation->param('Body');
495
496
        my $flavour =
497
            C4::Context->preference('marcflavour') eq 'UNIMARC'
498
            ? 'UNIMARCAUTH'
499
            : 'MARC21';
500
501
        my $record;
502
503
        my $frameworkcode = $c->validation->param('x-framework-id');
504
        if ( $c->req->headers->content_type =~ m/application\/marcxml\+xml/ ) {
505
            $record = MARC::Record->new_from_xml( $body, 'UTF-8', $flavour );
506
        } elsif ( $c->req->headers->content_type =~ m/application\/marc-in-json/ ) {
507
            $record = MARC::Record->new_from_mij_structure( $body );
508
        } elsif ( $c->req->headers->content_type =~ m/application\/marc/ ) {
509
            $record = MARC::Record->new_from_usmarc( $body );
510
        } else {
511
            return $c->render(
512
                status  => 406,
513
                openapi => [
514
                    "application/marcxml+xml",
515
                    "application/marc-in-json",
516
                    "application/marc"
517
                ]
518
            );
519
        }
520
521
        my ( $duplicatebiblionumber, $duplicatetitle );
522
            ( $duplicatebiblionumber, $duplicatetitle ) = FindDuplicate($record);
523
524
        my $confirm_not_duplicate = $c->validation->param('x-confirm-not-duplicate');
525
526
        return $c->render(
527
            status  => 400,
528
            openapi => {
529
                error => "Duplicate biblio $duplicatebiblionumber"
530
            }
531
        ) unless !$duplicatebiblionumber || $confirm_not_duplicate;
532
533
        my ( $biblionumber, $oldbibitemnum );
534
            ( $biblionumber, $oldbibitemnum ) = AddBiblio( $record, $frameworkcode );
535
536
        $c->render(
537
            status  => 200,
538
            openapi => { id => $biblionumber }
539
        );
540
    }
541
    catch {
542
        $c->unhandled_exception($_);
543
    };
544
}
545
483
1;
546
1;
(-)a/api/v1/swagger/paths/biblios.yaml (+56 lines)
Lines 1-4 Link Here
1
---
1
---
2
"/biblios":
3
  post:
4
    x-mojo-to: Biblios#add
5
    operationId: addBiblio
6
    tags:
7
      - biblios
8
    summary: Add biblio
9
    parameters:
10
      - name: Body
11
        in: body
12
        description: A JSON object or the Marc string describing a biblio
13
        required: true
14
        schema:
15
          type:
16
            - string
17
            - object
18
      - $ref: "../swagger.yaml#/parameters/framework_id_header"
19
      - $ref: "../swagger.yaml#/parameters/confirm_not_duplicate_header"
20
    produces:
21
      - application/json
22
    responses:
23
      "200":
24
        description: A biblio
25
      "400":
26
        description: Bad request
27
        schema:
28
          $ref: "../swagger.yaml#/definitions/error"
29
      "401":
30
        description: Authentication required
31
        schema:
32
          $ref: "../swagger.yaml#/definitions/error"
33
      "403":
34
        description: Access forbidden
35
        schema:
36
          $ref: "../swagger.yaml#/definitions/error"
37
      "406":
38
        description: Not acceptable
39
        schema:
40
          type: array
41
          description: Accepted content-types
42
          items:
43
            type: string
44
      "500":
45
        description: |
46
          Internal server error. Possible `error_code` attribute values:
47
48
          * `internal_server_error`
49
        schema:
50
          $ref: "../swagger.yaml#/definitions/error"
51
      "503":
52
        description: Under maintenance
53
        schema:
54
          $ref: "../swagger.yaml#/definitions/error"
55
    x-koha-authorization:
56
      permissions:
57
        editcatalogue: edit_catalogue
2
"/biblios/{biblio_id}":
58
"/biblios/{biblio_id}":
3
  get:
59
  get:
4
    x-mojo-to: Biblios#get
60
    x-mojo-to: Biblios#get
(-)a/api/v1/swagger/swagger.yaml (+15 lines)
Lines 137-142 paths: Link Here
137
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains
137
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains
138
  "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
138
  "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
139
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id}
139
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id}
140
  "/biblios":
141
    $ref: "./paths/biblios.yaml#/~1biblios"
140
  "/biblios/{biblio_id}":
142
  "/biblios/{biblio_id}":
141
    $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}"
143
    $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}"
142
  "/biblios/{biblio_id}/checkouts":
144
  "/biblios/{biblio_id}/checkouts":
Lines 336-341 parameters: Link Here
336
    name: agreement_period_id
338
    name: agreement_period_id
337
    required: true
339
    required: true
338
    type: integer
340
    type: integer
341
  framework_id_header:
342
    description: Framework id. Use when content type is not application/json
343
    name: x-framework-id
344
    in: header
345
    required: false
346
    type: string
347
  confirm_not_duplicate_header:
348
    description: Confirm the posted element is not a duplicate
349
    name: x-confirm-not-duplicate
350
    in: header
351
    required: false
352
    type: integer
353
339
  identity_provider_id_pp:
354
  identity_provider_id_pp:
340
    description: Authentication provider internal identifier
355
    description: Authentication provider internal identifier
341
    in: path
356
    in: path
(-)a/t/db_dependent/api/v1/biblios.t (-2 / +427 lines)
Lines 20-26 use Modern::Perl; Link Here
20
use utf8;
20
use utf8;
21
use Encode;
21
use Encode;
22
22
23
use Test::More tests => 8;
23
use Test::More tests => 9;
24
use Test::MockModule;
24
use Test::MockModule;
25
use Test::Mojo;
25
use Test::Mojo;
26
use Test::Warn;
26
use Test::Warn;
Lines 713-715 subtest 'set_rating() tests' => sub { Link Here
713
    $schema->storage->txn_rollback;
713
    $schema->storage->txn_rollback;
714
714
715
};
715
};
716
- 
716
717
718
subtest 'post() tests' => sub {
719
720
    plan tests => 11;
721
722
    $schema->storage->txn_begin;
723
724
    my $patron = $builder->build_object(
725
        {
726
            class => 'Koha::Patrons',
727
            value => { flags => 0 } # no permissions
728
        }
729
    );
730
    my $password = 'thePassword123';
731
    $patron->set_password( { password => $password, skip_validation => 1 } );
732
    my $userid = $patron->userid;
733
734
    my $frameworkcode = 'BKS';
735
    my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?>
736
<record
737
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
738
    xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
739
    xmlns="http://www.loc.gov/MARC21/slim">
740
741
  <leader>01102pam a2200289 a 7500</leader>
742
  <controlfield tag="001">2504398</controlfield>
743
  <controlfield tag="005">20200421093816.0</controlfield>
744
  <controlfield tag="008">920610s1993    caub         s001 0 eng  </controlfield>
745
  <datafield tag="010" ind1=" " ind2=" ">
746
    <subfield code="a">   92021731 </subfield>
747
  </datafield>
748
  <datafield tag="020" ind1=" " ind2=" ">
749
    <subfield code="a">05200784381 (Test marcxml)</subfield>
750
  </datafield>
751
  <datafield tag="020" ind1=" " ind2=" ">
752
    <subfield code="a">05200784461 (Test marcxml)</subfield>
753
  </datafield>
754
  <datafield tag="040" ind1=" " ind2=" ">
755
    <subfield code="a">DLC</subfield>
756
    <subfield code="c">DLC</subfield>
757
    <subfield code="d">DLC</subfield>
758
  </datafield>
759
  <datafield tag="041" ind1="0" ind2=" ">
760
    <subfield code="a">enggrc</subfield>
761
  </datafield>
762
  <datafield tag="050" ind1="0" ind2="0">
763
    <subfield code="a">PA522</subfield>
764
    <subfield code="b">.M38 1993</subfield>
765
  </datafield>
766
  <datafield tag="082" ind1="0" ind2="0">
767
    <subfield code="a">480</subfield>
768
    <subfield code="2">20</subfield>
769
  </datafield>
770
  <datafield tag="100" ind1="1" ind2=" ">
771
    <subfield code="a">Mastronarde, Donald J.</subfield>
772
    <subfield code="9">389</subfield>
773
  </datafield>
774
  <datafield tag="245" ind1="1" ind2="0">
775
    <subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield>
776
    <subfield code="c">Donald J. Mastronarde.</subfield>
777
  </datafield>
778
  <datafield tag="260" ind1=" " ind2=" ">
779
    <subfield code="a">Berkeley :</subfield>
780
    <subfield code="b">University of California Press,</subfield>
781
    <subfield code="c">c1993.</subfield>
782
  </datafield>
783
  <datafield tag="300" ind1=" " ind2=" ">
784
    <subfield code="a">ix, 425 p. :</subfield>
785
    <subfield code="b">maps ;</subfield>
786
    <subfield code="c">26 cm.</subfield>
787
  </datafield>
788
  <datafield tag="500" ind1=" " ind2=" ">
789
    <subfield code="a">Includes index.</subfield>
790
  </datafield>
791
  <datafield tag="650" ind1=" " ind2="0">
792
    <subfield code="a">Attic Greek dialect</subfield>
793
    <subfield code="9">7</subfield>
794
  </datafield>
795
  <datafield tag="856" ind1="4" ind2="2">
796
    <subfield code="3">Contributor biographical information</subfield>
797
    <subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield>
798
  </datafield>
799
  <datafield tag="856" ind1="4" ind2="2">
800
    <subfield code="3">Publisher description</subfield>
801
    <subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield>
802
  </datafield>
803
  <datafield tag="906" ind1=" " ind2=" ">
804
    <subfield code="a">7</subfield>
805
    <subfield code="b">cbc</subfield>
806
    <subfield code="c">orignew</subfield>
807
    <subfield code="d">1</subfield>
808
    <subfield code="e">ocip</subfield>
809
    <subfield code="f">19</subfield>
810
    <subfield code="g">y-gencatlg</subfield>
811
  </datafield>
812
  <datafield tag="942" ind1=" " ind2=" ">
813
    <subfield code="2">ddc</subfield>
814
    <subfield code="c">BK</subfield>
815
  </datafield>
816
  <datafield tag="955" ind1=" " ind2=" ">
817
    <subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield>
818
  </datafield>
819
  <datafield tag="999" ind1=" " ind2=" ">
820
    <subfield code="c">3</subfield>
821
    <subfield code="d">3</subfield>
822
  </datafield>
823
</record>|;
824
825
    my $mij = q|{
826
  "fields": [
827
    {
828
      "001": "2504398"
829
    },
830
    {
831
      "005": "20200421093816.0"
832
    },
833
    {
834
      "008": "920610s1993    caub         s001 0 eng  "
835
    },
836
    {
837
      "010": {
838
        "ind1": " ",
839
        "subfields": [
840
          {
841
            "a": "   92021731 "
842
          }
843
        ],
844
        "ind2": " "
845
      }
846
    },
847
    {
848
      "020": {
849
        "subfields": [
850
          {
851
            "a": "05200784382 (Test mij)"
852
          }
853
        ],
854
        "ind2": " ",
855
        "ind1": " "
856
      }
857
    },
858
    {
859
      "020": {
860
        "subfields": [
861
          {
862
            "a": "05200784462 (Test mij)"
863
          }
864
        ],
865
        "ind1": " ",
866
        "ind2": " "
867
      }
868
    },
869
    {
870
      "040": {
871
        "subfields": [
872
          {
873
            "a": "DLC"
874
          },
875
          {
876
            "c": "DLC"
877
          },
878
          {
879
            "d": "DLC"
880
          }
881
        ],
882
        "ind2": " ",
883
        "ind1": " "
884
      }
885
    },
886
    {
887
      "041": {
888
        "ind2": " ",
889
        "subfields": [
890
          {
891
            "a": "enggrc"
892
          }
893
        ],
894
        "ind1": "0"
895
      }
896
    },
897
    {
898
      "050": {
899
        "subfields": [
900
          {
901
            "a": "PA522"
902
          },
903
          {
904
            "b": ".M38 1993"
905
          }
906
        ],
907
        "ind1": "0",
908
        "ind2": "0"
909
      }
910
    },
911
    {
912
      "082": {
913
        "subfields": [
914
          {
915
            "a": "480"
916
          },
917
          {
918
            "2": "20"
919
          }
920
        ],
921
        "ind2": "0",
922
        "ind1": "0"
923
      }
924
    },
925
    {
926
      "100": {
927
        "ind2": " ",
928
        "subfields": [
929
          {
930
            "a": "Mastronarde, Donald J."
931
          },
932
          {
933
            "9": "389"
934
          }
935
        ],
936
        "ind1": "1"
937
      }
938
    },
939
    {
940
      "245": {
941
        "ind1": "1",
942
        "subfields": [
943
          {
944
            "a": "Introduction to Attic Greek  (Using mij) /"
945
          },
946
          {
947
            "c": "Donald J. Mastronarde."
948
          }
949
        ],
950
        "ind2": "0"
951
      }
952
    },
953
    {
954
      "260": {
955
        "subfields": [
956
          {
957
            "a": "Berkeley :"
958
          },
959
          {
960
            "b": "University of California Press,"
961
          },
962
          {
963
            "c": "c1993."
964
          }
965
        ],
966
        "ind2": " ",
967
        "ind1": " "
968
      }
969
    },
970
    {
971
      "300": {
972
        "ind1": " ",
973
        "subfields": [
974
          {
975
            "a": "ix, 425 p. :"
976
          },
977
          {
978
            "b": "maps ;"
979
          },
980
          {
981
            "c": "26 cm."
982
          }
983
        ],
984
        "ind2": " "
985
      }
986
    },
987
    {
988
      "500": {
989
        "subfields": [
990
          {
991
            "a": "Includes index."
992
          }
993
        ],
994
        "ind1": " ",
995
        "ind2": " "
996
      }
997
    },
998
    {
999
      "650": {
1000
        "subfields": [
1001
          {
1002
            "a": "Attic Greek dialect"
1003
          },
1004
          {
1005
            "9": "7"
1006
          }
1007
        ],
1008
        "ind2": "0",
1009
        "ind1": " "
1010
      }
1011
    },
1012
    {
1013
      "856": {
1014
        "subfields": [
1015
          {
1016
            "3": "Contributor biographical information"
1017
          },
1018
          {
1019
            "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html"
1020
          }
1021
        ],
1022
        "ind2": "2",
1023
        "ind1": "4"
1024
      }
1025
    },
1026
    {
1027
      "856": {
1028
        "ind1": "4",
1029
        "subfields": [
1030
          {
1031
            "3": "Publisher description"
1032
          },
1033
          {
1034
            "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html"
1035
          }
1036
        ],
1037
        "ind2": "2"
1038
      }
1039
    },
1040
    {
1041
      "906": {
1042
        "subfields": [
1043
          {
1044
            "a": "7"
1045
          },
1046
          {
1047
            "b": "cbc"
1048
          },
1049
          {
1050
            "c": "orignew"
1051
          },
1052
          {
1053
            "d": "1"
1054
          },
1055
          {
1056
            "e": "ocip"
1057
          },
1058
          {
1059
            "f": "19"
1060
          },
1061
          {
1062
            "g": "y-gencatlg"
1063
          }
1064
        ],
1065
        "ind1": " ",
1066
        "ind2": " "
1067
      }
1068
    },
1069
    {
1070
      "942": {
1071
        "subfields": [
1072
          {
1073
            "2": "ddc"
1074
          },
1075
          {
1076
            "c": "BK"
1077
          }
1078
        ],
1079
        "ind2": " ",
1080
        "ind1": " "
1081
      }
1082
    },
1083
    {
1084
      "955": {
1085
        "subfields": [
1086
          {
1087
            "a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
1088
          }
1089
        ],
1090
        "ind2": " ",
1091
        "ind1": " "
1092
      }
1093
    },
1094
    {
1095
      "999": {
1096
        "subfields": [
1097
          {
1098
            "c": "3"
1099
          },
1100
          {
1101
            "d": "3"
1102
          }
1103
        ],
1104
        "ind1": " ",
1105
        "ind2": " "
1106
      }
1107
    }
1108
  ],
1109
  "leader": "01102pam a2200289 a 8500"
1110
}|;
1111
    my $marc = q|01102pam a2200289 a 9500001000800000005001700008008004100025010001700066020002800083020003500111040001800146041001100164050002100175082001200196100003200208245005800240260005600298300003300354500002000387650002700407856009500434856008700529906004500616942001200661955013000673999000900803250439820200421093816.0920610s1993    caub         s001 0 eng    a   92021731   a05200784383 (Test usmarc)  a05200784463 (Test usmarc)  aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek  (Using usmarc) /cDonald J. Mastronarde.  aBerkeley :bUniversity of California Press,cc1993.  aix, 425 p. :bmaps ;c26 cm.  aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html  a7bcbccorignewd1eocipf19gy-gencatlg  2ddccBK  apc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93  c3d3|;
1112
1113
    $t->post_ok("//$userid:$password@/api/v1/biblios")
1114
      ->status_is(403, 'Not enough permissions makes it return the right code');
1115
1116
    # Add permissions
1117
    $builder->build(
1118
        {
1119
            source => 'UserPermission',
1120
            value  => {
1121
                borrowernumber => $patron->borrowernumber,
1122
                module_bit     => 9,
1123
                code           => 'edit_catalogue'
1124
            }
1125
        }
1126
    );
1127
1128
    $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml)
1129
      ->status_is(200)
1130
      ->json_has('/id');
1131
1132
    $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode, 'x-confirm-not-duplicate' => 1} => $mij)
1133
      ->status_is(200)
1134
      ->json_has('/id');
1135
1136
    $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc)
1137
      ->status_is(200)
1138
      ->json_has('/id');
1139
1140
    $schema->storage->txn_rollback;
1141
};

Return to bug 31800