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 28-34 use XML::Simple; Link Here
28
use C4::XSLT     qw( XSLTParse4Display );
28
use C4::XSLT     qw( XSLTParse4Display );
29
use C4::Reserves qw( GetReserveStatus );
29
use C4::Reserves qw( GetReserveStatus );
30
use C4::Charset  qw( SetUTF8Flag );
30
use C4::Charset  qw( SetUTF8Flag );
31
use C4::Matcher;
31
use Koha::AuthorisedValues;
32
use Koha::AuthorisedValues;
33
use Koha::BiblioFrameworkMarcMatchers;
32
use Koha::ItemTypes;
34
use Koha::ItemTypes;
33
use Koha::Libraries;
35
use Koha::Libraries;
34
use Koha::Logger;
36
use Koha::Logger;
Lines 146-151 sub FindDuplicate { Link Here
146
    return @results;
148
    return @results;
147
}
149
}
148
150
151
sub FindDuplicateWithMatchingRules {
152
    my ($record, $frameworkcode) = @_;
153
154
    $frameworkcode //= '';
155
156
    my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
157
    if ($biblio_framework_marc_matcher) {
158
        my $matcher = C4::Matcher->fetch($biblio_framework_marc_matcher->marc_matcher_id);
159
        if ($matcher) {
160
            my @duplicates;
161
            my $max_matches = 1;
162
            my @matches = $matcher->get_matches($record, $max_matches);
163
            foreach my $match (@matches) {
164
                my $biblio = Koha::Biblios->find($match->{record_id});
165
                if ($biblio) {
166
                    push @duplicates, {
167
                        biblionumber => $biblio->biblionumber,
168
                        title => $biblio->title,
169
                        forbid_duplicate_creation => $biblio_framework_marc_matcher->forbid_duplicate_creation,
170
                    };
171
                }
172
            }
173
174
            return @duplicates;
175
        }
176
    }
177
178
    # If no matcher can be used, default to FindDuplicate
179
    my @results = FindDuplicate($record);
180
    my @duplicates;
181
    while ((my $biblionumber = shift @results) && (my $title = shift @results)) {
182
        push @duplicates, {
183
            biblionumber => $biblionumber,
184
            title => $title,
185
            forbid_duplicate_creation => 0,
186
        }
187
    }
188
189
    return @duplicates;
190
}
191
149
=head2 SimpleSearch
192
=head2 SimpleSearch
150
193
151
( $error, $results, $total_hits ) = SimpleSearch( $query, $offset, $max_results, [@servers], [%options] );
194
( $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 (+43 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
21
use Koha::Database;
22
23
use base qw(Koha::Object);
24
25
=head1 NAME
26
27
Koha::BiblioFrameworkMarcMatcher
28
29
=head1 API
30
31
=head2 Class Methods
32
33
=cut
34
35
=head3 type
36
37
=cut
38
39
sub _type {
40
    return 'BiblioFrameworkMarcMatcher';
41
}
42
43
1;
(-)a/Koha/BiblioFrameworkMarcMatchers.pm (+49 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
21
use Koha::Database;
22
23
use Koha::BiblioFrameworkMarcMatcher;
24
25
use base qw(Koha::Objects);
26
27
=head1 NAME
28
29
Koha::BiblioFrameworkMarcMatchers
30
31
=head1 API
32
33
=head2 Class Methods
34
35
=cut
36
37
=head3 type
38
39
=cut
40
41
sub _type {
42
    return 'BiblioFrameworkMarcMatcher';
43
}
44
45
sub object_class {
46
    return 'Koha::BiblioFrameworkMarcMatcher';
47
}
48
49
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 667-681 sub add { Link Here
667
667
668
        my $confirm_not_duplicate = $headers->header('x-confirm-not-duplicate');
668
        my $confirm_not_duplicate = $headers->header('x-confirm-not-duplicate');
669
669
670
        if ( !$confirm_not_duplicate ) {
670
        my ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record, $frameworkcode);
671
            my ( $duplicatebiblionumber, $duplicatetitle ) = FindDuplicate($record);
671
        if ( $duplicate && ( $duplicate->{forbid_duplicate_creation} || !$confirm_not_duplicate ) ) {
672
673
            return $c->render(
672
            return $c->render(
674
                status  => 400,
673
                status  => 400,
675
                openapi => {
674
                openapi => {
676
                    error => "Duplicate biblio $duplicatebiblionumber",
675
                    error => "Duplicate biblio $duplicate->{biblionumber}",
677
                }
676
                }
678
            ) if $duplicatebiblionumber;
677
            );
679
        }
678
        }
680
679
681
        my ($biblio_id) = C4::Biblio::AddBiblio( $record, $frameworkcode, { record_source_id => $record_source_id } );
680
        my ($biblio_id) = C4::Biblio::AddBiblio( $record, $frameworkcode, { record_source_id => $record_source_id } );
(-)a/acqui/neworderempty.pl (-31 / +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
181
        #if duplicate record found and user did not decide yet, first warn user
178
        #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
179
        #and let them choose between using a new record or an existing record
183
        Load_Duplicate($duplicatetitle);
180
        #(if the matching rule does not forbid it)
181
        my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
182
            {
183
                template_name => "acqui/neworderempty_duplicate.tt",
184
                query         => $input,
185
                type          => "intranet",
186
                flagsrequired => { acquisition => 'order_manage' },
187
            }
188
        );
189
190
        my $marcflavour = uc C4::Context->preference("marcflavour");
191
        $template->param(
192
            basketno     => $basketno,
193
            booksellerid => $basket->{'booksellerid'},
194
            breedingid   => $breedingid,
195
            duplicate    => $duplicate,
196
            $marcflavour => 1
197
        );
198
199
        output_html_with_http_headers $input, $cookie, $template->output;
184
        exit;
200
        exit;
185
    }
201
    }
186
202
Lines 608-633 sub MARCfindbreeding { Link Here
608
    }
624
    }
609
    return -1;
625
    return -1;
610
}
626
}
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 (-28 / +53 lines)
Lines 23-35 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;
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) {
55
        if ($frameworkcode ne '') {
56
            $framework = Koha::BiblioFrameworks->find($frameworkcode);
57
        } else {
58
            $framework = Koha::BiblioFramework->new({ frameworkcode => '', frameworktext => __('Default framework') })
59
        }
60
61
        $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
51
    }
62
    }
52
    $template->param( framework => $framework );
63
    $template->param( framework => $framework );
53
} elsif ( $op eq 'cud-add_validate' ) {
64
    $template->param( biblio_framework_marc_matcher => $biblio_framework_marc_matcher );
54
    my $frameworkcode = $input->param('frameworkcode');
55
    my $frameworktext = $input->param('frameworktext');
56
    my $is_a_modif    = $input->param('is_a_modif');
57
65
58
    if ($is_a_modif) {
66
    my @matchers = C4::Matcher::GetMatcherList();
59
        my $framework = Koha::BiblioFrameworks->find($frameworkcode);
67
    $template->param('marc_matchers' => \@matchers);
60
        $framework->frameworktext($frameworktext);
68
} elsif ( $op eq 'cud-add_validate' ) {
61
        eval { $framework->store; };
69
    my $frameworkcode             = $input->param('frameworkcode');
62
        if ($@) {
70
    my $frameworktext             = $input->param('frameworktext');
63
            push @messages, { type => 'error', code => 'error_on_update' };
71
    my $marc_matcher_id           = $input->param('marc_matcher_id');
64
        } else {
72
    my $forbid_duplicate_creation = $input->param('forbid_duplicate_creation') // 0;
65
            push @messages, { type => 'message', code => 'success_on_update' };
73
    my $is_a_modif                = $input->param('is_a_modif');
66
        }
74
75
    my $framework;
76
    if ( $is_a_modif && $frameworkcode ne '' ) {
77
        $framework = Koha::BiblioFrameworks->find($frameworkcode);
67
    } else {
78
    } else {
68
        my $framework = Koha::BiblioFramework->new(
79
        $framework = Koha::BiblioFramework->new( { frameworkcode => $frameworkcode } );
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
    }
80
    }
81
82
    $framework->frameworktext($frameworktext);
83
    eval {
84
        $framework->store() unless $framework->frameworkcode eq '';
85
86
        my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatchers->find($frameworkcode);
87
        if ($marc_matcher_id) {
88
            unless ($biblio_framework_marc_matcher) {
89
                $biblio_framework_marc_matcher =
90
                    Koha::BiblioFrameworkMarcMatcher->new( { frameworkcode => $frameworkcode } );
91
            }
92
            $biblio_framework_marc_matcher->marc_matcher_id($marc_matcher_id);
93
            $biblio_framework_marc_matcher->forbid_duplicate_creation($forbid_duplicate_creation);
94
            $biblio_framework_marc_matcher->store();
95
        } elsif ($biblio_framework_marc_matcher) {
96
            $biblio_framework_marc_matcher->delete();
97
        }
98
    };
99
100
    if ($@) {
101
        push @messages, { type => 'error', code => $is_a_modif ? 'error_on_update' : 'error_on_insert' };
102
    } else {
103
        push @messages, { type => 'message', code => $is_a_modif ? 'success_on_update' : 'success_on_insert' };
104
    }
105
81
    $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
106
    $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
82
    $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
107
    $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
83
    $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
108
    $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
(-)a/cataloguing/addbiblio.pl (-7 / +5 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 796-804 if ( $op eq "cud-addbiblio" ) { Link Here
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 marc_matchers.use_for_manual_cataloging",
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 1129-1134 CREATE TABLE `biblio_framework` ( Link Here
1129
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1129
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1130
/*!40101 SET character_set_client = @saved_cs_client */;
1130
/*!40101 SET character_set_client = @saved_cs_client */;
1131
1131
1132
--
1133
-- Table structure for table `biblio_framework_marc_matcher`
1134
--
1135
1136
DROP TABLE IF EXISTS `biblio_framework_marc_matcher`;
1137
/*!40101 SET @saved_cs_client     = @@character_set_client */;
1138
/*!40101 SET character_set_client = utf8 */;
1139
CREATE TABLE `biblio_framework_marc_matcher` (
1140
  `frameworkcode` varchar(4) NOT NULL COMMENT 'MARC framework code',
1141
  `marc_matcher_id` int(11) NOT NULL COMMENT 'MARC matcher id',
1142
  `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',
1143
  PRIMARY KEY (`frameworkcode`),
1144
  KEY `biblio_framework_marc_matcher_ibfk_1` (`marc_matcher_id`),
1145
  CONSTRAINT `biblio_framework_marc_matcher_ibfk_1` FOREIGN KEY (`marc_matcher_id`) REFERENCES `marc_matchers` (`matcher_id`) ON DELETE CASCADE
1146
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
1147
/*!40101 SET character_set_client = @saved_cs_client */;
1148
1132
--
1149
--
1133
-- Table structure for table `biblio_metadata`
1150
-- Table structure for table `biblio_metadata`
1134
--
1151
--
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty_duplicate.tt (-14 / +16 lines)
Lines 35-41 Link Here
35
        <h1>Duplicate warning</h1>
35
        <h1>Duplicate warning</h1>
36
        <p
36
        <p
37
            >You selected a record from an external source that matches an existing record in your catalog:
37
            >You selected a record from an external source that matches an existing record in your catalog:
38
            <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></p
38
            <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></p
39
        >
39
        >
40
    </div>
40
    </div>
41
41
Lines 64-83 Link Here
64
            </div>
64
            </div>
65
        </div>
65
        </div>
66
66
67
        <div class="col-sm-4">
67
        [% UNLESS duplicate.forbid_duplicate_creation %]
68
            <div style="border: 1px solid #DDD; padding:1em;">
68
            <div class="col-sm-4">
69
                <form method="post" action="/cgi-bin/koha/acqui/neworderempty.pl">
69
                <div style="border: 1px solid #DDD; padding:1em;">
70
                    [% INCLUDE 'csrf-token.inc' %]
70
                    <form method="post" action="/cgi-bin/koha/acqui/neworderempty.pl">
71
                    <h4>Create new record</h4>
71
                        [% INCLUDE 'csrf-token.inc' %]
72
                    <p>Create a new record by importing the external (duplicate) record.</p>
72
                        <h4>Create new record</h4>
73
                    <input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
73
                        <p>Create a new record by importing the external (duplicate) record.</p>
74
                    <input type="hidden" name="basketno" value="[% basketno | html %]" />
74
                        <input type="hidden" name="booksellerid" value="[% booksellerid | html %]" />
75
                    <input type="hidden" name="breedingid" value="[% breedingid | html %]" />
75
                        <input type="hidden" name="basketno" value="[% basketno | html %]" />
76
                    <input type="hidden" name="op" value="cud-use_external_source" />
76
                        <input type="hidden" name="breedingid" value="[% breedingid | html %]" />
77
                    <input type="submit" class="btn btn-primary" value="Create new" />
77
                        <input type="hidden" name="op" value="cud-use_external_source" />
78
                </form>
78
                        <input type="submit" class="btn btn-primary" value="Create new" />
79
                    </form>
80
                </div>
79
            </div>
81
            </div>
80
        </div>
82
        [% END %]
81
    </div>
83
    </div>
82
[% END %]
84
[% END %]
83
85
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/biblio_framework.tt (-3 / +35 lines)
Lines 131-140 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 %]
137
                    </li>
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 %]>
153
                                        [% marc_matcher.description | html %]
154
                                    </option>
155
                                [% END %]
156
                            </select>
157
                        </li>
158
                    [% END %]
159
160
                    <li>
161
                        <label for="forbid_duplicate_creation">[% t('Forbid creation of duplicate') | html %]</label>
162
                        <input type="checkbox" id="forbid_duplicate_creation" name="forbid_duplicate_creation" value="1" [% IF biblio_framework_marc_matcher.forbid_duplicate_creation %]checked[% END %]>
163
                        <div class="hint">
164
                            [% 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 %]
165
                        </div>
166
                     </li>
138
                </ol>
167
                </ol>
139
            </fieldset>
168
            </fieldset>
140
            <fieldset class="action">
169
            <fieldset class="action">
Lines 191-196 Link Here
191
                                    <li
220
                                    <li
192
                                        ><a class="dropdown-item" href="marctagstructure.pl?frameworkcode="><i class="fa-solid fa-eye"></i> MARC structure</a></li
221
                                        ><a class="dropdown-item" href="marctagstructure.pl?frameworkcode="><i class="fa-solid fa-eye"></i> MARC structure</a></li
193
                                    >
222
                                    >
223
                                    <li
224
                                        ><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
225
                                    >
194
                                    <!-- Trigger modal -->
226
                                    <!-- Trigger modal -->
195
                                    <li
227
                                    <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)"
228
                                        ><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 / +81 lines)
Lines 831-885 Link Here
831
831
832
    [% UNLESS ( number ) %]
832
    [% UNLESS ( number ) %]
833
        <!-- show duplicate warning on tab 0 only -->
833
        <!-- show duplicate warning on tab 0 only -->
834
        [% IF ( duplicatebiblionumber ) %]
834
        [% IF ( duplicate ) %]
835
            <div class="alert alert-warning">
835
            <div class="alert alert-warning">
836
                <h3>Duplicate record suspected</h3>
836
                [% IF duplicate.forbid_duplicate_creation %]
837
                <p
837
                    <h3>Duplicate record detected</h3>
838
                    >Is this a duplicate of
838
                    <p
839
                    <a
839
                        >This is a duplicate of
840
                        href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicatebiblionumber | uri %]"
840
                        <a
841
                        onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicatebiblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
841
                            href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]"
842
                        >[% duplicatetitle | html %] <i class="fa-solid fa-window-restore"></i
842
                            onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
843
                    ></a>
843
                            >[% duplicate.title | html %] <i class="fa-solid fa-window-restore"></i
844
                    ?</p
844
                        ></a>
845
                >
845
                        </p
846
                [% IF ( CAN_user_editcatalogue_edit_items ) %]
846
                    >
847
                    <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
847
                    [% IF ( CAN_user_editcatalogue_edit_items ) %]
848
                        [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
848
                        <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
849
                            <input type="hidden" name="barcode" value="[% barcode | html %]" />
849
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
850
                            <input type="hidden" name="branch" value="[% branch | html %]" />
850
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
851
                            <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
851
                                <input type="hidden" name="branch" value="[% branch | html %]" />
852
                            <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
852
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
853
                            <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
853
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
854
                        [% END %]
854
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
855
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
855
                            [% END %]
856
                        <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Yes, edit existing items</button>
856
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
857
                    </form>
857
                            <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Edit existing items</button>
858
                [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
858
                        </form>
859
                    <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
859
                    [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
860
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
860
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
861
                        <input type="submit" value="Yes: View existing items (you may not add items to existing records)" />
861
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
862
                    </form>
862
                            <input type="submit" value="View existing items (you may not add items to existing records)" />
863
                        </form>
864
                    [% ELSE %]
865
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
866
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
867
                            <input type="submit" value="View existing items" />
868
                        </form>
869
                    [% END %]
863
                [% ELSE %]
870
                [% ELSE %]
864
                    <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
871
                    <h3>Duplicate record suspected</h3>
865
                        <input type="hidden" name="biblionumber" value="[% duplicatebiblionumber | html %]" />
872
                    <p
866
                        <input type="submit" value="Yes: View existing items" />
873
                        >Is this a duplicate of
874
                        <a
875
                            href="/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]"
876
                            onclick="openWindow('/cgi-bin/koha/catalogue/MARCdetail.pl?biblionumber=[% duplicate.biblionumber | uri %]&amp;popup=1', 'DuplicateBiblio','800','600'); return false;"
877
                            >[% duplicate.title | html %] <i class="fa-solid fa-window-restore"></i
878
                        ></a>
879
                        ?</p
880
                    >
881
                    [% IF ( CAN_user_editcatalogue_edit_items ) %]
882
                        <form action="/cgi-bin/koha/cataloguing/additem.pl" method="get">
883
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
884
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
885
                                <input type="hidden" name="branch" value="[% branch | html %]" />
886
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
887
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
888
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
889
                            [% END %]
890
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
891
                            <button type="submit" class="new"><i class="fa-fw fa-solid fa-pencil" aria-hidden="true"></i> Yes, edit existing items</button>
892
                        </form>
893
                    [% ELSIF ( circborrowernumber ) # Coming from fast cataloging %]
894
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
895
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
896
                            <input type="submit" value="Yes: View existing items (you may not add items to existing records)" />
897
                        </form>
898
                    [% ELSE %]
899
                        <form action="/cgi-bin/koha/catalogue/detail.pl" method="get">
900
                            <input type="hidden" name="biblionumber" value="[% duplicate.biblionumber | html %]" />
901
                            <input type="submit" value="Yes: View existing items" />
902
                        </form>
903
                    [% END %]
904
                    <form action="/cgi-bin/koha/cataloguing/addbiblio.pl" method="get">
905
                        [% IF ( CAN_user_editcatalogue_edit_items || CAN_user_editcatalogue_fast_cataloging ) %]
906
                            [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
907
                                <input type="hidden" name="barcode" value="[% barcode | html %]" />
908
                                <input type="hidden" name="branch" value="[% branch | html %]" />
909
                                <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
910
                                <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
911
                                <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
912
                            [% END %]
913
                            <button type="submit" class="new" onclick="confirmnotdup('items'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
914
                        [% ELSE %]
915
                            <button type="submit" class="new" onclick="confirmnotdup('view'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
916
                        [% END %]
867
                    </form>
917
                    </form>
868
                [% END %]
918
                [% END %]
869
                <form action="/cgi-bin/koha/cataloguing/addbiblio.pl" method="get">
870
                    [% IF ( CAN_user_editcatalogue_edit_items || CAN_user_editcatalogue_fast_cataloging ) %]
871
                        [% IF ( circborrowernumber ) # It is possible we have come from fast cataloging - include the fields %]
872
                            <input type="hidden" name="barcode" value="[% barcode | html %]" />
873
                            <input type="hidden" name="branch" value="[% branch | html %]" />
874
                            <input type="hidden" name="circborrowernumber" value="[% circborrowernumber | html %]" />
875
                            <input type="hidden" name="stickyduedate" value="[% stickyduedate | html %]" />
876
                            <input type="hidden" name="duedatespec" value="[% duedatespec | html %]" />
877
                        [% END %]
878
                        <button type="submit" class="new" onclick="confirmnotdup('items'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
879
                    [% ELSE %]
880
                        <button type="submit" class="new" onclick="confirmnotdup('view'); return false;"><i class="fa fa-fw fa-save"></i> No, save as new record</button>
881
                    [% END %]
882
                </form>
883
            </div>
919
            </div>
884
            <!-- /.dialog.alert -->
920
            <!-- /.dialog.alert -->
885
        [% END # /IF duplicatebiblionumber %]
921
        [% 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 / +74 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
    $mock_zebra->launch_zebra;
1389
    t::lib::Mocks::mock_preference('SearchEngine', 'Zebra' );
1390
1391
    my $schema = Koha::Database->schema;
1392
1393
    # Unlike with FindDuplicate, we need the biblio to exist
1394
    my $biblio = Koha::Biblios->find(51);
1395
    unless ($biblio) {
1396
        $schema->resultset('Biblio')->create(
1397
            {
1398
                biblionumber => 51,
1399
                frameworkcode => '',
1400
                title => 'Administração da produção /',
1401
                datecreated  => DateTime->now->ymd,
1402
            }
1403
        );
1404
    }
1405
1406
    $schema->txn_begin;
1407
1408
    $schema->resultset('MarcMatcher')->delete;
1409
1410
    my $record = MARC::Record->new;
1411
    $record->add_fields(
1412
        [ '020', ' ', ' ', a => '9788522421718' ],
1413
        [ '245', '0', '0', a => 'Administração da produção /' ]
1414
    );
1415
    my ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1416
    is($duplicate && $duplicate->{biblionumber}, 51, 'Without any matcher, same result than FindDuplicate');
1417
1418
    # Make sure the matcher is used by configuring it badly first, it should return no duplicate
1419
    my $matcher = C4::Matcher->new('biblio', 1000);
1420
    $matcher->add_matchpoint('issn', 1000, [ { tag => '020', subfields => 'a', offset => 0 } ]);
1421
    $matcher->store();
1422
1423
    my $biblio_framework_marc_matcher = Koha::BiblioFrameworkMarcMatcher->new(
1424
        {
1425
            frameworkcode   => '',
1426
            marc_matcher_id => $matcher->{id},
1427
        }
1428
    );
1429
    $biblio_framework_marc_matcher->store();
1430
1431
    ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1432
    ok(!defined $duplicate, 'Matcher is used and returns no duplicates');
1433
1434
    # Now fix the matcher and make sure it returns a duplicate
1435
    $matcher->{matchpoints} = [];
1436
    $matcher->add_matchpoint('isbn', 1000, [ { tag => '020', subfields => 'a', offset => 0 } ]);
1437
    $matcher->store();
1438
1439
    ($duplicate) = C4::Search::FindDuplicateWithMatchingRules($record);
1440
    is($duplicate && $duplicate->{biblionumber}, 51, 'Matcher is used and returns a duplicate');
1441
1442
    $schema->txn_rollback;
1443
};
1444
1372
# Make sure that following tests are not using our config settings
1445
# Make sure that following tests are not using our config settings
1373
Koha::Caches->get_instance('config')->flush_all;
1446
Koha::Caches->get_instance('config')->flush_all;
1374
1447
1375
- 

Return to bug 15248