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

(-)a/C4/Matcher.pm (-15 / +25 lines)
Lines 19-24 package C4::Matcher; Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Koha::Database;
22
use Koha::SearchEngine;
23
use Koha::SearchEngine;
23
use Koha::SearchEngine::Search;
24
use Koha::SearchEngine::Search;
24
use Koha::SearchEngine::QueryBuilder;
25
use Koha::SearchEngine::QueryBuilder;
Lines 70-76 C4::Matcher - find MARC records matching another one Link Here
70
71
71
=head2 GetMatcherList
72
=head2 GetMatcherList
72
73
73
  my @matchers = C4::Matcher::GetMatcherList();
74
  my @matchers = C4::Matcher::GetMatcherList($filters);
74
75
75
Returns an array of hashrefs list all matchers
76
Returns an array of hashrefs list all matchers
76
present in the database.  Each hashref includes:
77
present in the database.  Each hashref includes:
Lines 78-96 present in the database. Each hashref includes: Link Here
78
 * matcher_id
79
 * matcher_id
79
 * code
80
 * code
80
 * description
81
 * description
82
 * record_type
83
84
C<$filters> is an optional hashref parameter that allows to filter the result. Useful keys are:
85
86
=over
87
88
=item * C<record_type>
89
90
=back
91
92
See L<DBIx::Class::ResultSet/search> for more info
93
94
=head3 Examples
95
96
    @matchers = C4::Matcher::GetMatcherList();
97
    @matchers = C4::Matcher::GetMatcherList({ record_type => 'biblio' });
98
    @matchers = C4::Matcher::GetMatcherList({ record_type => 'authority' });
81
99
82
=cut
100
=cut
83
101
84
sub GetMatcherList {
102
sub GetMatcherList {
85
    my $dbh = C4::Context->dbh;
103
    my ($filters) = @_;
86
104
87
    my $sth = $dbh->prepare_cached("SELECT matcher_id, code, description FROM marc_matchers ORDER BY matcher_id");
105
    my $rs = Koha::Database->schema->resultset('MarcMatcher');
88
    $sth->execute();
106
89
    my @results = ();
107
    return $rs->search( $filters // {}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' } )->all;
90
    while ( my $row = $sth->fetchrow_hashref ) {
91
        push @results, $row;
92
    }
93
    return @results;
94
}
108
}
95
109
96
=head2 GetMatcherId
110
=head2 GetMatcherId
Lines 171-182 sub fetch { Link Here
171
    $sth->finish();
185
    $sth->finish();
172
    return unless defined $row;
186
    return unless defined $row;
173
187
174
    my $self = {};
188
    my $self = {%$row};
175
    $self->{'id'}          = $row->{'matcher_id'};
189
    $self->{id} = delete $self->{matcher_id};
176
    $self->{'record_type'} = $row->{'record_type'};
177
    $self->{'code'}        = $row->{'code'};
178
    $self->{'description'} = $row->{'description'};
179
    $self->{'threshold'}   = int( $row->{'threshold'} );
180
    bless $self, $class;
190
    bless $self, $class;
181
191
182
    # matchpoints
192
    # matchpoints
(-)a/C4/Search.pm (+43 lines)
Lines 45-51 use XML::Simple; Link Here
45
use C4::XSLT     qw( XSLTParse4Display );
45
use C4::XSLT     qw( XSLTParse4Display );
46
use C4::Reserves qw( GetReserveStatus );
46
use C4::Reserves qw( GetReserveStatus );
47
use C4::Charset  qw( SetUTF8Flag );
47
use C4::Charset  qw( SetUTF8Flag );
48
use C4::Matcher;
48
use Koha::AuthorisedValues;
49
use Koha::AuthorisedValues;
50
use Koha::BiblioFrameworkMarcMatchers;
49
use Koha::ItemTypes;
51
use Koha::ItemTypes;
50
use Koha::Libraries;
52
use Koha::Libraries;
51
use Koha::Logger;
53
use Koha::Logger;
Lines 144-149 sub FindDuplicate { Link Here
144
    return @results;
146
    return @results;
145
}
147
}
146
148
149
sub FindDuplicateWithMatchingRules {
150
    my ( $record, $frameworkcode ) = @_;
151
152
    $frameworkcode //= '';
153
154
    my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
155
    if ($biblio_framework_marc_matcher) {
156
        my $matcher = C4::Matcher->fetch( $biblio_framework_marc_matcher->marc_matcher_id );
157
        if ($matcher) {
158
            my @duplicates;
159
            my $max_matches = 1;
160
            my @matches     = $matcher->get_matches( $record, $max_matches );
161
            foreach my $match (@matches) {
162
                my $biblio = Koha::Biblios->find( $match->{record_id} );
163
                if ($biblio) {
164
                    push @duplicates, {
165
                        biblionumber              => $biblio->biblionumber,
166
                        title                     => $biblio->title,
167
                        forbid_duplicate_creation => $biblio_framework_marc_matcher->forbid_duplicate_creation,
168
                    };
169
                }
170
            }
171
172
            return @duplicates;
173
        }
174
    }
175
176
    # If no matcher can be used, default to FindDuplicate
177
    my @results = FindDuplicate($record);
178
    my @duplicates;
179
    while ( ( my $biblionumber = shift @results ) && ( my $title = shift @results ) ) {
180
        push @duplicates, {
181
            biblionumber              => $biblionumber,
182
            title                     => $title,
183
            forbid_duplicate_creation => 0,
184
        };
185
    }
186
187
    return @duplicates;
188
}
189
147
=head2 SimpleSearch
190
=head2 SimpleSearch
148
191
149
( $error, $results, $total_hits ) = SimpleSearch( $query, $offset, $max_results, [@servers], [%options] );
192
( $error, $results, $total_hits ) = SimpleSearch( $query, $offset, $max_results, [@servers], [%options] );
(-)a/Koha/BiblioFramework.pm (+17 lines)
Lines 31-36 Koha::BiblioFramework - Koha BiblioFramework Object class Link Here
31
31
32
=cut
32
=cut
33
33
34
=head3 delete
35
36
See L<Koha::Object/delete>
37
38
=cut
39
40
sub delete {
41
    my ($self) = @_;
42
43
    my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find( $self->frameworkcode );
44
    if ($biblio_framework_marc_matcher) {
45
        $biblio_framework_marc_matcher->delete();
46
    }
47
48
    $self->SUPER::delete();
49
}
50
34
=head3 type
51
=head3 type
35
52
36
=cut
53
=cut
(-)a/Koha/BiblioFrameworkMarcMatcher.pm (+42 lines)
Line 0 Link Here
1
package Koha::BiblioFrameworkMarcMatcher;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Koha::Database;
21
22
use base qw(Koha::Object);
23
24
=head1 NAME
25
26
Koha::BiblioFrameworkMarcMatcher
27
28
=head1 API
29
30
=head2 Class Methods
31
32
=cut
33
34
=head3 type
35
36
=cut
37
38
sub _type {
39
    return 'BiblioFrameworkMarcMatcher';
40
}
41
42
1;
(-)a/Koha/BiblioFrameworkMarcMatchers.pm (+48 lines)
Line 0 Link Here
1
package Koha::BiblioFrameworkMarcMatchers;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Koha::Database;
21
22
use Koha::BiblioFrameworkMarcMatcher;
23
24
use base qw(Koha::Objects);
25
26
=head1 NAME
27
28
Koha::BiblioFrameworkMarcMatchers
29
30
=head1 API
31
32
=head2 Class Methods
33
34
=cut
35
36
=head3 type
37
38
=cut
39
40
sub _type {
41
    return 'BiblioFrameworkMarcMatcher';
42
}
43
44
sub object_class {
45
    return 'Koha::BiblioFrameworkMarcMatcher';
46
}
47
48
1;
(-)a/Koha/REST/V1/Biblios.pm (-6 / +5 lines)
Lines 23-29 use Koha::Biblios; Link Here
23
use Koha::DateUtils;
23
use Koha::DateUtils;
24
use Koha::Ratings;
24
use Koha::Ratings;
25
use C4::Biblio qw( DelBiblio AddBiblio ModBiblio );
25
use C4::Biblio qw( DelBiblio AddBiblio ModBiblio );
26
use C4::Search qw( FindDuplicate );
26
use C4::Search;
27
27
28
use C4::Auth qw( haspermission );
28
use C4::Auth qw( haspermission );
29
use C4::Barcodes::ValueBuilder;
29
use C4::Barcodes::ValueBuilder;
Lines 672-686 sub add { Link Here
672
672
673
        my $confirm_not_duplicate = $headers->header('x-confirm-not-duplicate');
673
        my $confirm_not_duplicate = $headers->header('x-confirm-not-duplicate');
674
674
675
        if ( !$confirm_not_duplicate ) {
675
        my ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record, $frameworkcode);
676
            my ( $duplicatebiblionumber, $duplicatetitle ) = FindDuplicate($record);
676
        if ( $duplicate && ( $duplicate->{forbid_duplicate_creation} || !$confirm_not_duplicate ) ) {
677
678
            return $c->render(
677
            return $c->render(
679
                status  => 400,
678
                status  => 400,
680
                openapi => {
679
                openapi => {
681
                    error => "Duplicate biblio $duplicatebiblionumber",
680
                    error => "Duplicate biblio $duplicate->{biblionumber}",
682
                }
681
                }
683
            ) if $duplicatebiblionumber;
682
            );
684
        }
683
        }
685
684
686
        my ($biblio_id) = C4::Biblio::AddBiblio( $record, $frameworkcode, { record_source_id => $record_source_id } );
685
        my ($biblio_id) = C4::Biblio::AddBiblio( $record, $frameworkcode, { record_source_id => $record_source_id } );
(-)a/acqui/neworderempty.pl (-30 / +24 lines)
Lines 83-89 use C4::Biblio qw( Link Here
83
);
83
);
84
use C4::Output qw( output_and_exit output_html_with_http_headers );
84
use C4::Output qw( output_and_exit output_html_with_http_headers );
85
use C4::Members;
85
use C4::Members;
86
use C4::Search qw( FindDuplicate );
86
use C4::Search;
87
87
88
#needed for z3950 import:
88
#needed for z3950 import:
89
use C4::ImportBatch qw( SetImportRecordStatus SetMatchedBiblionumber GetImportRecordMarc );
89
use C4::ImportBatch qw( SetImportRecordStatus SetMatchedBiblionumber GetImportRecordMarc );
Lines 172-186 if ( $ordernumber eq '' and defined $breedingid ) { Link Here
172
        $marcrecord->delete_field($item);
172
        $marcrecord->delete_field($item);
173
    }
173
    }
174
174
175
    my $duplicatetitle;
175
    # look for duplicates
176
176
    my ($duplicate) = C4::Search::FindDuplicateWithMatchingRules( $marcrecord, $frameworkcode );
177
    #look for duplicates
177
    if ( $duplicate && $op ne 'cud-use_external_source' ) {
178
    ( $biblionumber, $duplicatetitle ) = FindDuplicate($marcrecord);
179
    if ( $biblionumber && $op ne 'cud-use_external_source' ) {
180
178
181
        #if duplicate record found and user did not decide yet, first warn user
179
        #if duplicate record found and user did not decide yet, first warn user
182
        #and let them choose between using a new record or an existing record
180
        #and let them choose between using a new record or an existing record
183
        Load_Duplicate($duplicatetitle);
181
        #(if the matching rule does not forbid it)
182
        my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
183
            {
184
                template_name => "acqui/neworderempty_duplicate.tt",
185
                query         => $input,
186
                type          => "intranet",
187
                flagsrequired => { acquisition => 'order_manage' },
188
            }
189
        );
190
191
        my $marcflavour = uc C4::Context->preference("marcflavour");
192
        $template->param(
193
            basketno     => $basketno,
194
            booksellerid => $basket->{'booksellerid'},
195
            breedingid   => $breedingid,
196
            duplicate    => $duplicate,
197
            $marcflavour => 1
198
        );
199
200
        output_html_with_http_headers $input, $cookie, $template->output;
184
        exit;
201
        exit;
185
    }
202
    }
186
203
Lines 608-633 sub MARCfindbreeding { Link Here
608
    }
625
    }
609
    return -1;
626
    return -1;
610
}
627
}
611
612
sub Load_Duplicate {
613
    my ($duplicatetitle) = @_;
614
    ( $template, $loggedinuser, $cookie ) = get_template_and_user(
615
        {
616
            template_name => "acqui/neworderempty_duplicate.tt",
617
            query         => $input,
618
            type          => "intranet",
619
            flagsrequired => { acquisition => 'order_manage' },
620
        }
621
    );
622
623
    $template->param(
624
        biblionumber                                     => $biblionumber,
625
        basketno                                         => $basketno,
626
        booksellerid                                     => $basket->{'booksellerid'},
627
        breedingid                                       => $breedingid,
628
        duplicatetitle                                   => $duplicatetitle,
629
        ( uc( C4::Context->preference("marcflavour") ) ) => 1
630
    );
631
632
    output_html_with_http_headers $input, $cookie, $template->output;
633
}
(-)a/admin/biblio_framework.pl (-32 / +58 lines)
Lines 23-36 use CGI qw ( -utf8 ); Link Here
23
use C4::Context;
23
use C4::Context;
24
use C4::Auth   qw( get_template_and_user );
24
use C4::Auth   qw( get_template_and_user );
25
use C4::Output qw( output_html_with_http_headers );
25
use C4::Output qw( output_html_with_http_headers );
26
use C4::Matcher;
26
use Koha::Biblios;
27
use Koha::Biblios;
27
use Koha::BiblioFramework;
28
use Koha::BiblioFramework;
28
use Koha::BiblioFrameworks;
29
use Koha::BiblioFrameworks;
30
use Koha::BiblioFrameworkMarcMatcher;
31
use Koha::BiblioFrameworkMarcMatchers;
29
use Koha::Caches;
32
use Koha::Caches;
33
use Koha::I18N;
30
34
31
my $input         = CGI->new;
35
my $input         = CGI->new;
32
my $frameworkcode = $input->param('frameworkcode') || q||;
36
my $frameworkcode = $input->param('frameworkcode');
33
my $op            = $input->param('op')            || q|list|;
37
my $op            = $input->param('op') || q|list|;
34
my $cache         = Koha::Caches->get_instance();
38
my $cache         = Koha::Caches->get_instance();
35
my @messages;
39
my @messages;
36
40
Lines 46-83 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
46
my $dbh = C4::Context->dbh;
50
my $dbh = C4::Context->dbh;
47
if ( $op eq 'add_form' ) {
51
if ( $op eq 'add_form' ) {
48
    my $framework;
52
    my $framework;
49
    if ($frameworkcode) {
53
    my $biblio_framework_marc_matcher;
50
        $framework = Koha::BiblioFrameworks->find($frameworkcode);
54
    if ( defined $frameworkcode ) {
51
    }
55
        if ( $frameworkcode ne '' ) {
52
    $template->param( framework => $framework );
56
            $framework = Koha::BiblioFrameworks->find($frameworkcode);
53
} elsif ( $op eq 'cud-add_validate' ) {
57
        } else {
54
    my $frameworkcode = $input->param('frameworkcode');
58
            $framework =
55
    my $frameworktext = $input->param('frameworktext');
59
                Koha::BiblioFramework->new( { frameworkcode => '', frameworktext => __('Default framework') } );
56
    my $is_a_modif    = $input->param('is_a_modif');
60
        }
57
61
58
    if ($is_a_modif) {
62
        $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
59
        my $framework = Koha::BiblioFrameworks->find($frameworkcode);
60
        $framework->frameworktext($frameworktext);
61
        eval { $framework->store; };
62
        if ($@) {
63
            push @messages, { type => 'error', code => 'error_on_update' };
64
        } else {
65
            push @messages, { type => 'message', code => 'success_on_update' };
66
        }
67
    } else {
68
        my $framework = Koha::BiblioFramework->new(
69
            {
70
                frameworkcode => $frameworkcode,
71
                frameworktext => $frameworktext,
72
            }
73
        );
74
        eval { $framework->store; };
75
        if ($@) {
76
            push @messages, { type => 'error', code => 'error_on_insert' };
77
        } else {
78
            push @messages, { type => 'message', code => 'success_on_insert' };
79
        }
80
    }
63
    }
64
    $template->param( framework                     => $framework );
65
    $template->param( biblio_framework_marc_matcher => $biblio_framework_marc_matcher );
66
67
    my @matchers = C4::Matcher::GetMatcherList();
68
    $template->param( 'marc_matchers' => \@matchers );
69
} elsif ( $op eq 'cud-add_validate' ) {
70
    my $frameworkcode             = $input->param('frameworkcode');
71
    my $frameworktext             = $input->param('frameworktext');
72
    my $marc_matcher_id           = $input->param('marc_matcher_id');
73
    my $forbid_duplicate_creation = $input->param('forbid_duplicate_creation') // 0;
74
    my $is_a_modif                = $input->param('is_a_modif');
75
76
    my $framework;
77
    if ( $is_a_modif && $frameworkcode ne '' ) {
78
        $framework = Koha::BiblioFrameworks->find($frameworkcode);
79
    } else {
80
        $framework = Koha::BiblioFramework->new( { frameworkcode => $frameworkcode } );
81
    }
82
83
    $framework->frameworktext($frameworktext);
84
    eval {
85
        $framework->store() unless $framework->frameworkcode eq '';
86
87
        my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
88
        if ($marc_matcher_id) {
89
            unless ($biblio_framework_marc_matcher) {
90
                $biblio_framework_marc_matcher =
91
                    Koha::BiblioFrameworkMarcMatcher->new( { frameworkcode => $frameworkcode } );
92
            }
93
            $biblio_framework_marc_matcher->marc_matcher_id($marc_matcher_id);
94
            $biblio_framework_marc_matcher->forbid_duplicate_creation($forbid_duplicate_creation);
95
            $biblio_framework_marc_matcher->store();
96
        } elsif ($biblio_framework_marc_matcher) {
97
            $biblio_framework_marc_matcher->delete();
98
        }
99
    };
100
101
    if ($@) {
102
        push @messages, { type => 'error', code => $is_a_modif ? 'error_on_update' : 'error_on_insert' };
103
    } else {
104
        push @messages, { type => 'message', code => $is_a_modif ? 'success_on_update' : 'success_on_insert' };
105
    }
106
81
    $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
107
    $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
82
    $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
108
    $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
83
    $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
109
    $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
(-)a/cataloguing/addbiblio.pl (-9 / +7 lines)
Lines 37-43 use C4::Biblio qw( Link Here
37
    TransformHtmlToMarc
37
    TransformHtmlToMarc
38
    ApplyMarcOverlayRules
38
    ApplyMarcOverlayRules
39
);
39
);
40
use C4::Search qw( FindDuplicate enabled_staff_search_views );
40
use C4::Search qw( enabled_staff_search_views );
41
use C4::Auth   qw( get_template_and_user haspermission );
41
use C4::Auth   qw( get_template_and_user haspermission );
42
use C4::Context;
42
use C4::Context;
43
use MARC::Record;
43
use MARC::Record;
Lines 694-707 if ( $op eq "cud-addbiblio" ) { Link Here
694
    $record = TransformHtmlToMarc( $input, 1 );
694
    $record = TransformHtmlToMarc( $input, 1 );
695
695
696
    # check for a duplicate
696
    # check for a duplicate
697
    my ( $duplicatebiblionumber, $duplicatetitle );
697
    my $duplicate;
698
    if ( !$is_a_modif ) {
698
    if ( !$is_a_modif ) {
699
        ( $duplicatebiblionumber, $duplicatetitle ) = FindDuplicate($record);
699
        ($duplicate) = C4::Search::FindDuplicateWithMatchingRules( $record, $frameworkcode );
700
    }
700
    }
701
    my $confirm_not_duplicate = $input->param('confirm_not_duplicate');
701
    my $confirm_not_duplicate = $input->param('confirm_not_duplicate');
702
702
703
    # it is not a duplicate (determined either by Koha itself or by user checking it's not a duplicate)
703
    # it is not a duplicate (determined either by Koha itself or by user checking it's not a duplicate)
704
    if ( !$duplicatebiblionumber or $confirm_not_duplicate ) {
704
    if ( !$duplicate or ( !$duplicate->{forbid_duplicate_creation} and $confirm_not_duplicate ) ) {
705
        my $oldbibitemnum;
705
        my $oldbibitemnum;
706
        if ($is_a_modif) {
706
        if ($is_a_modif) {
707
            ModBiblio(
707
            ModBiblio(
Lines 794-804 if ( $op eq "cud-addbiblio" ) { Link Here
794
        # it may be a duplicate, warn the user and do nothing
794
        # it may be a duplicate, warn the user and do nothing
795
        build_tabs( $template, $record, $dbh, $encoding, $input );
795
        build_tabs( $template, $record, $dbh, $encoding, $input );
796
        $template->param(
796
        $template->param(
797
            biblionumber          => $biblionumber,
797
            biblionumber     => $biblionumber,
798
            biblioitemnumber      => $biblioitemnumber,
798
            biblioitemnumber => $biblioitemnumber,
799
            duplicatebiblionumber => $duplicatebiblionumber,
799
            duplicate        => $duplicate,
800
            duplicatebibid        => $duplicatebiblionumber,
801
            duplicatetitle        => $duplicatetitle,
802
        );
800
        );
803
    }
801
    }
804
802
(-)a/installer/data/mysql/atomicupdate/bug-15248.pl (+29 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number  => "15248",
5
    description => "Add biblio_framework_marc_matcher table",
6
    up          => sub {
7
        my ($args) = @_;
8
        my ( $dbh, $out ) = @$args{qw(dbh out)};
9
10
        unless ( TableExists('biblio_framework_marc_matcher') ) {
11
            $dbh->do(
12
                q{
13
                CREATE TABLE biblio_framework_marc_matcher (
14
                    frameworkcode VARCHAR(4) NOT NULL COMMENT 'MARC framework code',
15
                    marc_matcher_id INT(11) NOT NULL COMMENT 'MARC matcher id',
16
                    forbid_duplicate_creation TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Do not show an option to create a duplicate record when a duplicate is found',
17
                    PRIMARY KEY (frameworkcode),
18
                    CONSTRAINT biblio_framework_marc_matcher_ibfk_1
19
                      FOREIGN KEY (marc_matcher_id) REFERENCES marc_matchers (matcher_id)
20
                      ON DELETE CASCADE
21
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
22
            }
23
            );
24
            say $out "Created new table biblio_framework_marc_matcher";
25
        } else {
26
            say $out "Table biblio_framework_marc_matcher already exists";
27
        }
28
    },
29
};
(-)a/installer/data/mysql/kohastructure.sql (+17 lines)
Lines 1135-1140 CREATE TABLE `biblio_framework` ( Link Here
1135
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1135
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1136
/*!40101 SET character_set_client = @saved_cs_client */;
1136
/*!40101 SET character_set_client = @saved_cs_client */;
1137
1137
1138
--
1139
-- Table structure for table `biblio_framework_marc_matcher`
1140
--
1141
1142
DROP TABLE IF EXISTS `biblio_framework_marc_matcher`;
1143
/*!40101 SET @saved_cs_client     = @@character_set_client */;
1144
/*!40101 SET character_set_client = utf8 */;
1145
CREATE TABLE `biblio_framework_marc_matcher` (
1146
  `frameworkcode` varchar(4) NOT NULL COMMENT 'MARC framework code',
1147
  `marc_matcher_id` int(11) NOT NULL COMMENT 'MARC matcher id',
1148
  `forbid_duplicate_creation` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Do not show an option to create a duplicate record when a duplicate is found',
1149
  PRIMARY KEY (`frameworkcode`),
1150
  KEY `biblio_framework_marc_matcher_ibfk_1` (`marc_matcher_id`),
1151
  CONSTRAINT `biblio_framework_marc_matcher_ibfk_1` FOREIGN KEY (`marc_matcher_id`) REFERENCES `marc_matchers` (`matcher_id`) ON DELETE CASCADE
1152
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1153
/*!40101 SET character_set_client = @saved_cs_client */;
1154
1138
--
1155
--
1139
-- Table structure for table `biblio_metadata`
1156
-- Table structure for table `biblio_metadata`
1140
--
1157
--
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt (-30 / +32 lines)
Lines 38-44 Link Here
38
        [% ELSE %]
38
        [% ELSE %]
39
            <p>The details you entered match an existing record in your catalog:</p>
39
            <p>The details you entered match an existing record in your catalog:</p>
40
        [% END %]
40
        [% END %]
41
        <a target="_blank" title="Open in new window" href="[% PROCESS biblio_a_href biblionumber => biblionumber %]"><i class="fa-solid fa-window-restore"></i> [% duplicatetitle | html %]</a>
41
        <a target="_blank" title="Open in new window" href="[% PROCESS biblio_a_href biblionumber => duplicate.biblionumber %]"><i class="fa-solid fa-window-restore"></i> [% duplicate.title | html %]</a>
42
    </div>
42
    </div>
43
43
44
    <div class="row">
44
    <div class="row">
Lines 66-103 Link Here
66
            </div>
66
            </div>
67
        </div>
67
        </div>
68
68
69
        <div class="col-sm-4">
69
        [% UNLESS duplicate.forbid_duplicate_creation %]
70
            <div style="border: 1px solid #DDD; padding:1em;">
70
            <div class="col-sm-4">
71
                [% IF breedingid %]
71
                <div style="border: 1px solid #DDD; padding:1em;">
72
                    <form method="post" action="/cgi-bin/koha/acqui/neworderempty.pl">
72
                    [% IF breedingid %]
73
                        [% INCLUDE 'csrf-token.inc' %]
73
                        <form method="post" action="/cgi-bin/koha/acqui/neworderempty.pl">
74
                        <h4>Create new record</h4>
74
                            [% INCLUDE 'csrf-token.inc' %]
75
                        <p>Create a new record by importing the external (duplicate) record.</p>
75
                            <h4>Create new record</h4>
76
                        <input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
76
                            <p>Create a new record by importing the external (duplicate) record.</p>
77
                        <input type="hidden" name="basketno" value="[% basketno | html %]" />
77
                            <input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
78
                        <input type="hidden" name="breedingid" value="[% breedingid | html %]" />
78
                            <input type="hidden" name="basketno" value="[% basketno | html %]" />
79
                        <input type="hidden" name="op" value="cud-use_external_source" />
79
                            <input type="hidden" name="breedingid" value="[% breedingid | html %]" />
80
                        <input type="submit" class="btn btn-primary" value="Create new" />
80
                            <input type="hidden" name="op" value="cud-use_external_source" />
81
                    </form>
81
                            <input type="submit" class="btn btn-primary" value="Create new" />
82
                [% ELSE %]
82
                        </form>
83
                    <form method="post" action="/cgi-bin/koha/acqui/addorder.pl">
83
                    [% ELSE %]
84
                        [% INCLUDE 'csrf-token.inc' %]
84
                        <form method="post" action="/cgi-bin/koha/acqui/addorder.pl">
85
                        <h4>Create new record</h4>
85
                            [% INCLUDE 'csrf-token.inc' %]
86
                        <p>Create a new record with the details you entered.</p>
86
                            <h4>Create new record</h4>
87
                        <input type="hidden" name="op" value="cud-order" />
87
                            <p>Create a new record with the details you entered.</p>
88
                        <input type="hidden" name="confirm_not_duplicate" value="1" />
88
                            <input type="hidden" name="op" value="cud-order" />
89
                        [% FOREACH var IN vars_loop %]
89
                            <input type="hidden" name="confirm_not_duplicate" value="1" />
90
                            [% FOREACH val IN var.values %]
90
                            [% FOREACH var IN vars_loop %]
91
                                [% IF var.name != 'confirm_not_duplicate' %]
91
                                [% FOREACH val IN var.values %]
92
                                    <input type="hidden" name="[% var.name | html %]" value="[% val | html %]" />
92
                                    [% IF var.name != 'confirm_not_duplicate' %]
93
                                        <input type="hidden" name="[% var.name | html %]" value="[% val | html %]" />
94
                                    [% END %]
93
                                [% END %]
95
                                [% END %]
94
                            [% END %]
96
                            [% END %]
95
                        [% END %]
97
                            <button type="submit" class="btn btn-primary">Create new</button>
96
                        <button type="submit" class="btn btn-primary">Create new</button>
98
                        </form>
97
                    </form>
99
                    [% END %]
98
                [% END %]
100
                </div>
99
            </div>
101
            </div>
100
        </div>
102
        [% END %]
101
    </div>
103
    </div>
102
[% END %]
104
[% END %]
103
105
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/biblio_framework.tt (-3 / +33 lines)
Lines 131-139 Link Here
131
                        </li>
131
                        </li>
132
                    [% END %]
132
                    [% END %]
133
                    <li>
133
                    <li>
134
                        <label for="description" class="required">Description: </label>
134
                        [% IF framework && frameworkcode == '' %]
135
                        <input type="text" name="frameworktext" id="description" size="40" maxlength="80" value="[% framework.frameworktext | html %]" required="required" class="required" />
135
                            <label for="description">Description: </label>
136
                        <span class="required">Required</span>
136
                            <span>[% framework.frameworktext | html %]</span>
137
                        [% ELSE %]
138
                            <label for="description" class="required">Description: </label>
139
                            <input type="text" name="frameworktext" id="description" size="40" maxlength="80" value="[% framework.frameworktext | html %]" required="required" class="required" />
140
                            <span class="required">Required</span>
141
                        [% END %]
142
                    </li>
143
144
                    [% IF marc_matchers.size > 0 %]
145
                        <li>
146
                            <label for="marc_matcher_id">[% t('Matching rules used to find duplicates:') | html %]</label>
147
                            <select name="marc_matcher_id" id="marc_matcher_id">
148
                                <option value="">[% t('None (use the default duplicates finding mechanism)') | html %]</option>
149
150
                                [% FOREACH marc_matcher IN marc_matchers %]
151
                                    [% SET selected = marc_matcher.matcher_id == biblio_framework_marc_matcher.marc_matcher_id %]
152
                                    <option value="[% marc_matcher.matcher_id | html %]" [% IF selected %]selected[% END %]> [% marc_matcher.description | html %] </option>
153
                                [% END %]
154
                            </select>
155
                        </li>
156
                    [% END %]
157
158
                    <li>
159
                        <label for="forbid_duplicate_creation">[% t('Forbid creation of duplicate') | html %]</label>
160
                        <input type="checkbox" id="forbid_duplicate_creation" name="forbid_duplicate_creation" value="1" [% IF biblio_framework_marc_matcher.forbid_duplicate_creation %]checked[% END %] />
161
                        <div class="hint">
162
                            [% t('If the selected matching rule finds a duplicate and this option is enabled, it will not be possible to create a duplicate. This has no effect if no matching rule is selected.') | html %]
163
                        </div>
137
                    </li>
164
                    </li>
138
                </ol>
165
                </ol>
139
            </fieldset>
166
            </fieldset>
Lines 191-196 Link Here
191
                                    <li
218
                                    <li
192
                                        ><a class="dropdown-item" href="marctagstructure.pl?frameworkcode="><i class="fa-solid fa-eye"></i> MARC structure</a></li
219
                                        ><a class="dropdown-item" href="marctagstructure.pl?frameworkcode="><i class="fa-solid fa-eye"></i> MARC structure</a></li
193
                                    >
220
                                    >
221
                                    <li
222
                                        ><a class="dropdown-item" href="/cgi-bin/koha/admin/biblio_framework.pl?op=add_form&frameworkcode="><i class="fa-solid fa-pencil"></i> Edit</a></li
223
                                    >
194
                                    <!-- Trigger modal -->
224
                                    <!-- Trigger modal -->
195
                                    <li
225
                                    <li
196
                                        ><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#exportModal_default" title="Export framework structure (fields, subfields) to a spreadsheet file (.csv or .ods)"
226
                                        ><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#exportModal_default" title="Export framework structure (fields, subfields) to a spreadsheet file (.csv or .ods)"
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt (+2 lines)
Lines 590-595 Link Here
590
                        <th>#</th>
590
                        <th>#</th>
591
                        <th>Code</th>
591
                        <th>Code</th>
592
                        <th>Description</th>
592
                        <th>Description</th>
593
                        <th>Record type</th>
593
                        <th class="no-export">Actions</th>
594
                        <th class="no-export">Actions</th>
594
                    </tr>
595
                    </tr>
595
                    [% FOREACH available_matching_rule IN available_matching_rules %]
596
                    [% FOREACH available_matching_rule IN available_matching_rules %]
Lines 597-602 Link Here
597
                            <td>[% available_matching_rule.matcher_id | html %]</td>
598
                            <td>[% available_matching_rule.matcher_id | html %]</td>
598
                            <td>[% available_matching_rule.code | html %]</td>
599
                            <td>[% available_matching_rule.code | html %]</td>
599
                            <td>[% available_matching_rule.description | html %]</td>
600
                            <td>[% available_matching_rule.description | html %]</td>
601
                            <td>[% available_matching_rule.record_type | html %]</td>
600
                            <td class="actions">
602
                            <td class="actions">
601
                                <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/matching-rules.pl?op=edit_matching_rule&amp;matcher_id=[% available_matching_rule.matcher_id | uri %]"
603
                                <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/matching-rules.pl?op=edit_matching_rule&amp;matcher_id=[% available_matching_rule.matcher_id | uri %]"
602
                                    ><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a
604
                                    ><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt (-45 / +80 lines)
Lines 836-890 Link Here
836
836
837
    [% UNLESS ( number ) %]
837
    [% UNLESS ( number ) %]
838
        <!-- show duplicate warning on tab 0 only -->
838
        <!-- show duplicate warning on tab 0 only -->
839
        [% IF ( duplicatebiblionumber ) %]
839
        [% IF ( duplicate ) %]
840
            <div class="alert alert-warning">
840
            <div class="alert alert-warning">
841
                <h3>Duplicate record suspected</h3>
841
                [% IF duplicate.forbid_duplicate_creation %]
842
                <p
842
                    <h3>Duplicate record detected</h3>
843
                    >Is this a duplicate of
843
                    <p
844
                    <a
844
                        >This is a duplicate of
845
                        href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicatebiblionumber | uri %]"
845
                        <a
846
                        onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicatebiblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
846
                            href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]"
847
                        >[% duplicatetitle | html %] <i class="fa-solid fa-window-restore"></i
847
                            onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
848
                    ></a>
848
                            >[% duplicate.title | html %] <i class="fa-solid fa-window-restore"></i
849
                    ?</p
849
                        ></a>
850
                >
850
                    </p>
851
                [% IF ( CAN_user_editcatalogue_edit_items ) %]
851
                    [% IF ( CAN_user_editcatalogue_edit_items ) %]
852
                    <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
852
                        <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
853
                        [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
853
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
854
                            <input type="hidden" name="barcode" value="[% barcode | html %]" />
854
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
855
                            <input type="hidden" name="branch" value="[% branch | html %]" />
855
                                <input type="hidden" name="branch" value="[% branch | html %]" />
856
                            <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
856
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
857
                            <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
857
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
858
                            <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
858
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
859
                        [% END %]
859
                            [% END %]
860
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
860
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
861
                        <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Yes, edit existing items</button>
861
                            <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Edit existing items</button>
862
                    </form>
862
                        </form>
863
                [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
863
                    [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
864
                    <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
864
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
865
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
865
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
866
                        <input type="submit" value="Yes: View existing items (you may not add items to existing records)" />
866
                            <input type="submit" value="View existing items (you may not add items to existing records)" />
867
                    </form>
867
                        </form>
868
                    [% ELSE %]
869
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
870
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
871
                            <input type="submit" value="View existing items" />
872
                        </form>
873
                    [% END %]
868
                [% ELSE %]
874
                [% ELSE %]
869
                    <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
875
                    <h3>Duplicate record suspected</h3>
870
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
876
                    <p
871
                        <input type="submit" value="Yes: View existing items" />
877
                        >Is this a duplicate of
878
                        <a
879
                            href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]"
880
                            onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
881
                            >[% duplicate.title | html %] <i class="fa-solid fa-window-restore"></i
882
                        ></a>
883
                        ?</p
884
                    >
885
                    [% IF ( CAN_user_editcatalogue_edit_items ) %]
886
                        <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
887
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
888
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
889
                                <input type="hidden" name="branch" value="[% branch | html %]" />
890
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
891
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
892
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
893
                            [% END %]
894
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
895
                            <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Yes, edit existing items</button>
896
                        </form>
897
                    [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
898
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
899
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
900
                            <input type="submit" value="Yes: View existing items (you may not add items to existing records)" />
901
                        </form>
902
                    [% ELSE %]
903
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
904
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
905
                            <input type="submit" value="Yes: View existing items" />
906
                        </form>
907
                    [% END %]
908
                    <form action="/cgi-bin/koha/cataloguing/addbiblio.pl" method="get">
909
                        [% IF ( CAN_user_editcatalogue_edit_items || CAN_user_editcatalogue_fast_cataloging ) %]
910
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
911
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
912
                                <input type="hidden" name="branch" value="[% branch | html %]" />
913
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
914
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
915
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
916
                            [% END %]
917
                            <button type="submit" class="new" onclick="confirmnotdup('items'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
918
                        [% ELSE %]
919
                            <button type="submit" class="new" onclick="confirmnotdup('view'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
920
                        [% END %]
872
                    </form>
921
                    </form>
873
                [% END %]
922
                [% END %]
874
                <form action="/cgi-bin/koha/cataloguing/addbiblio.pl" method="get">
875
                    [% IF ( CAN_user_editcatalogue_edit_items || CAN_user_editcatalogue_fast_cataloging ) %]
876
                        [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
877
                            <input type="hidden" name="barcode" value="[% barcode | html %]" />
878
                            <input type="hidden" name="branch" value="[% branch | html %]" />
879
                            <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
880
                            <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
881
                            <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
882
                        [% END %]
883
                        <button type="submit" class="new" onclick="confirmnotdup('items'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
884
                    [% ELSE %]
885
                        <button type="submit" class="new" onclick="confirmnotdup('view'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
886
                    [% END %]
887
                </form>
888
            </div>
923
            </div>
889
            <!-- /.dialog.alert -->
924
            <!-- /.dialog.alert -->
890
        [% END # /IF duplicatebiblionumber %]
925
        [% END # /IF duplicatebiblionumber %]
(-)a/t/db_dependent/Matcher.t (-1 / +5 lines)
Lines 32-38 my $builder = t::lib::TestBuilder->new; Link Here
32
$schema->storage->txn_begin;
32
$schema->storage->txn_begin;
33
33
34
subtest 'GetMatcherList' => sub {
34
subtest 'GetMatcherList' => sub {
35
    plan tests => 9;
35
    plan tests => 11;
36
36
37
    $schema->resultset('MarcMatcher')->delete_all;
37
    $schema->resultset('MarcMatcher')->delete_all;
38
    my $matcher1 = $builder->build(
38
    my $matcher1 = $builder->build(
Lines 70-75 subtest 'GetMatcherList' => sub { Link Here
70
70
71
    $testmatcher->description('match on ISSN');
71
    $testmatcher->description('match on ISSN');
72
    is( $testmatcher->description(), 'match on ISSN', 'testing code accessor' );
72
    is( $testmatcher->description(), 'match on ISSN', 'testing code accessor' );
73
74
    @matchers = C4::Matcher::GetMatcherList( { record_type => 'blue' } );
75
    is( scalar @matchers,            1,      'Filtering works' );
76
    is( $matchers[0]->{record_type}, 'blue', 'Filtering on record type works' );
73
};
77
};
74
78
75
subtest '_get_match_keys() tests' => sub {
79
subtest '_get_match_keys() tests' => sub {
(-)a/t/db_dependent/Search.t (-2 / +75 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use utf8;
20
use utf8;
21
21
22
use C4::AuthoritiesMarc qw( SearchAuthorities );
22
use C4::AuthoritiesMarc qw( SearchAuthorities );
23
use C4::Matcher;
23
use C4::XSLT;
24
use C4::XSLT;
24
require C4::Context;
25
require C4::Context;
25
26
Lines 27-39 require C4::Context; Link Here
27
use open ':std', ':encoding(utf8)';
28
use open ':std', ':encoding(utf8)';
28
29
29
use Test::NoWarnings;
30
use Test::NoWarnings;
30
use Test::More tests => 5;
31
use Test::More tests => 6;
31
use Test::MockModule;
32
use Test::MockModule;
32
use Test::Warn;
33
use Test::Warn;
33
use t::lib::Mocks;
34
use t::lib::Mocks;
34
use t::lib::Mocks::Zebra;
35
use t::lib::Mocks::Zebra;
35
36
36
use Koha::Caches;
37
use Koha::Caches;
38
use Koha::Database;
37
39
38
use MARC::Record;
40
use MARC::Record;
39
use File::Spec;
41
use File::Spec;
Lines 42-47 use File::Find; Link Here
42
44
43
use File::Temp qw/ tempdir /;
45
use File::Temp qw/ tempdir /;
44
use File::Path;
46
use File::Path;
47
use DateTime;
45
48
46
# Fall back to make sure that the Zebra process
49
# Fall back to make sure that the Zebra process
47
# and files get cleaned up
50
# and files get cleaned up
Lines 1369-1374 subtest 'FindDuplicate' => sub { Link Here
1369
1372
1370
};
1373
};
1371
1374
1375
subtest 'FindDuplicateWithMatchingRules' => sub {
1376
    plan tests => 3;
1377
1378
    my $marcflavour = 'MARC21';
1379
    my $mock_zebra  = t::lib::Mocks::Zebra->new( { marcflavour => $marcflavour } );
1380
    push @cleanup, $mock_zebra;
1381
1382
    mock_GetMarcSubfieldStructure($marcflavour);
1383
1384
    my $sourcedir = dirname(__FILE__) . "/data";
1385
    $mock_zebra->load_records(
1386
        sprintf( "%s/%s/zebraexport/biblio", $sourcedir, lc($marcflavour) ),
1387
        'iso2709', 'biblios', 1
1388
    );
1389
    $mock_zebra->launch_zebra;
1390
    t::lib::Mocks::mock_preference( 'SearchEngine', 'Zebra' );
1391
1392
    my $schema = Koha::Database->schema;
1393
1394
    # Unlike with FindDuplicate, we need the biblio to exist
1395
    my $biblio = Koha::Biblios->find(51);
1396
    unless ($biblio) {
1397
        $schema->resultset('Biblio')->create(
1398
            {
1399
                biblionumber  => 51,
1400
                frameworkcode => '',
1401
                title         => 'Administração da produção /',
1402
                datecreated   => DateTime->now->ymd,
1403
            }
1404
        );
1405
    }
1406
1407
    $schema->txn_begin;
1408
1409
    $schema->resultset('MarcMatcher')->delete;
1410
1411
    my $record = MARC::Record->new;
1412
    $record->add_fields(
1413
        [ '020', ' ', ' ', a => '9788522421718' ],
1414
        [ '245', '0', '0', a => 'Administração da produção /' ]
1415
    );
1416
    my ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1417
    is( $duplicate && $duplicate->{biblionumber}, 51, 'Without any matcher, same result than FindDuplicate' );
1418
1419
    # Make sure the matcher is used by configuring it badly first, it should return no duplicate
1420
    my $matcher = C4::Matcher->new( 'biblio', 1000 );
1421
    $matcher->add_matchpoint( 'issn', 1000, [ { tag => '020', subfields => 'a', offset => 0 } ] );
1422
    $matcher->store();
1423
1424
    my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatcher->new(
1425
        {
1426
            frameworkcode   => '',
1427
            marc_matcher_id => $matcher->{id},
1428
        }
1429
    );
1430
    $biblio_framework_marc_matcher->store();
1431
1432
    ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1433
    ok( !defined $duplicate, 'Matcher is used and returns no duplicates' );
1434
1435
    # Now fix the matcher and make sure it returns a duplicate
1436
    $matcher->{matchpoints} = [];
1437
    $matcher->add_matchpoint( 'isbn', 1000, [ { tag => '020', subfields => 'a', offset => 0 } ] );
1438
    $matcher->store();
1439
1440
    ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1441
    is( $duplicate && $duplicate->{biblionumber}, 51, 'Matcher is used and returns a duplicate' );
1442
1443
    $schema->txn_rollback;
1444
};
1445
1372
# Make sure that following tests are not using our config settings
1446
# Make sure that following tests are not using our config settings
1373
Koha::Caches->get_instance('config')->flush_all;
1447
Koha::Caches->get_instance('config')->flush_all;
1374
1448
1375
- 

Return to bug 15248