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

(-)a/misc/maintenance/search_for_data_inconsistencies.pl (-206 / +234 lines)
Lines 16-21 Link Here
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
use Koha::Script;
20
use Koha::Script;
20
use Koha::AuthorisedValues;
21
use Koha::AuthorisedValues;
21
use Koha::Authorities;
22
use Koha::Authorities;
Lines 80-87 pod2usage(1) if $options{'help'}; Link Here
80
81
81
# Set skip options based on check options
82
# Set skip options based on check options
82
set_skip_options();
83
set_skip_options();
84
83
# Set all check options to 1 if none are provided, unless specified skip options
85
# Set all check options to 1 if none are provided, unless specified skip options
84
set_all_check_options_if_none_provided();
86
set_all_check_options_if_none_provided();
87
85
# Run checks based on options
88
# Run checks based on options
86
CheckItemsBranch()       if $options{'check-branch'}    && !$options{'skip-branch'};
89
CheckItemsBranch()       if $options{'check-branch'}    && !$options{'skip-branch'};
87
CheckItemsAuthHeader()   if $options{'check-auth'}      && !$options{'skip-auth'};
90
CheckItemsAuthHeader()   if $options{'check-auth'}      && !$options{'skip-auth'};
Lines 100-116 sub handle_invalid_options { Link Here
100
103
101
# Set skip options based on check options
104
# Set skip options based on check options
102
sub set_skip_options {
105
sub set_skip_options {
106
103
    # If at least one check option is provided, set all skip options to 0
107
    # If at least one check option is provided, set all skip options to 0
104
    my $has_check_option = grep { $options{$_} } grep { /^check-/ } keys %options;
108
    my $has_check_option = grep { $options{$_} } grep { /^check-/ } keys %options;
105
    if ($has_check_option) {
109
    if ($has_check_option) {
110
106
        # if a least one skip option is provided, print a warning
111
        # if a least one skip option is provided, print a warning
107
        my $has_skip_option = grep { $options{$_} == 1 } grep { /^skip-/ } keys %options;
112
        my $has_skip_option = grep { $options{$_} == 1 } grep { /^skip-/ } keys %options;
108
        if ($has_skip_option) {
113
        if ($has_skip_option) {
109
            print("Warning : skip options are ignored when check options are provided\n")
114
            print("Warning : skip options are ignored when check options are provided\n");
110
        }
115
        }
116
111
        # Set all skip options to 0
117
        # Set all skip options to 0
112
        foreach my $key (keys %options) {
118
        foreach my $key ( keys %options ) {
113
            if ($key =~ /^skip-/) {
119
            if ( $key =~ /^skip-/ ) {
114
                $options{$key} = 0;
120
                $options{$key} = 0;
115
            }
121
            }
116
        }
122
        }
Lines 121-131 sub set_skip_options { Link Here
121
# Set all check options to 1 if none are provided, considering skip options
127
# Set all check options to 1 if none are provided, considering skip options
122
sub set_all_check_options_if_none_provided {
128
sub set_all_check_options_if_none_provided {
123
    my $any_check_option_provided = grep { $options{$_} } grep { /^check-/ } keys %options;
129
    my $any_check_option_provided = grep { $options{$_} } grep { /^check-/ } keys %options;
124
    if (!$any_check_option_provided) {
130
    if ( !$any_check_option_provided ) {
125
        foreach my $key (keys %options) {
131
        foreach my $key ( keys %options ) {
126
            if ($key =~ /^check-/) {
132
            if ( $key =~ /^check-/ ) {
127
                my $skip_key = $key;
133
                my $skip_key = $key;
128
                $skip_key =~ s/^check-/skip-/;
134
                $skip_key =~ s/^check-/skip-/;
135
129
                # Set check option to 1 unless the corresponding skip option indicated
136
                # Set check option to 1 unless the corresponding skip option indicated
130
                $options{$key} = 1 unless $options{$skip_key};
137
                $options{$key} = 1 unless $options{$skip_key};
131
            }
138
            }
Lines 134-394 sub set_all_check_options_if_none_provided { Link Here
134
}
141
}
135
142
136
sub CheckItemsBranch {
143
sub CheckItemsBranch {
137
    my $items = Koha::Items->search({ -or => { homebranch => undef, holdingbranch => undef }});
144
    my $items = Koha::Items->search( { -or => { homebranch => undef, holdingbranch => undef } } );
138
    if ( $items->count ) { new_section("Not defined items.homebranch and/or items.holdingbranch")}
145
    if ( $items->count ) { new_section("Not defined items.homebranch and/or items.holdingbranch") }
139
    while ( my $item = $items->next ) {
146
    while ( my $item = $items->next ) {
140
        if ( not $item->homebranch and not $item->holdingbranch ) {
147
        if ( not $item->homebranch and not $item->holdingbranch ) {
141
            new_item(sprintf "Item with itemnumber=%s and biblionumber=%s does not have homebranch and holdingbranch defined",  $item->itemnumber, $item->biblionumber);
148
            new_item(
142
            } elsif ( not $item->homebranch ) {
149
                sprintf
143
            new_item(sprintf "Item with itemnumber=%s and biblionumber=%s does not have homebranch defined", $item->itemnumber, $item->biblionumber);
150
                    "Item with itemnumber=%s and biblionumber=%s does not have homebranch and holdingbranch defined",
144
            } else {
151
                $item->itemnumber, $item->biblionumber
145
            new_item(sprintf "Item with itemnumber=%s and biblionumber=%s does not have holdingbranch defined", $item->itemnumber, $item->biblionumber);
152
            );
153
        } elsif ( not $item->homebranch ) {
154
            new_item(
155
                sprintf "Item with itemnumber=%s and biblionumber=%s does not have homebranch defined",
156
                $item->itemnumber, $item->biblionumber
157
            );
158
        } else {
159
            new_item(
160
                sprintf "Item with itemnumber=%s and biblionumber=%s does not have holdingbranch defined",
161
                $item->itemnumber, $item->biblionumber
162
            );
146
        }
163
        }
147
    }
164
    }
148
    if ( $items->count ) { new_hint("Edit these items and set valid homebranch and/or holdingbranch")}
165
    if ( $items->count ) { new_hint("Edit these items and set valid homebranch and/or holdingbranch") }
149
}
166
}
150
167
151
sub CheckItemsAuthHeader {
168
sub CheckItemsAuthHeader {
169
152
    # No join possible, FK is missing at DB level
170
    # No join possible, FK is missing at DB level
153
    my @auth_types = Koha::Authority::Types->search->get_column('authtypecode');
171
    my @auth_types  = Koha::Authority::Types->search->get_column('authtypecode');
154
    my $authorities = Koha::Authorities->search({authtypecode => { 'not in' => \@auth_types } });
172
    my $authorities = Koha::Authorities->search( { authtypecode => { 'not in' => \@auth_types } } );
155
    if ( $authorities->count ) {new_section("Invalid auth_header.authtypecode")}
173
    if ( $authorities->count ) { new_section("Invalid auth_header.authtypecode") }
156
    while ( my $authority = $authorities->next ) {
174
    while ( my $authority = $authorities->next ) {
157
        new_item(sprintf "Authority with authid=%s does not have a code defined (%s)", $authority->authid, $authority->authtypecode);
175
        new_item(
176
            sprintf "Authority with authid=%s does not have a code defined (%s)", $authority->authid,
177
            $authority->authtypecode
178
        );
158
    }
179
    }
159
    if ( $authorities->count ) {new_hint("Go to 'Home -> Administration -> Authority types' to define them")};
180
    if ( $authorities->count ) { new_hint("Go to 'Home -> Administration -> Authority types' to define them") }
160
    };
181
}
161
182
162
    sub CheckItemsStatus {
183
sub CheckItemsStatus {
163
        if ( C4::Context->preference('item-level_itypes') ) {
184
    if ( C4::Context->preference('item-level_itypes') ) {
164
            my $items_without_itype = Koha::Items->search( { -or => [itype => undef,itype => ''] } );
185
        my $items_without_itype = Koha::Items->search( { -or => [ itype => undef, itype => '' ] } );
165
            if ( $items_without_itype->count ) {
186
        if ( $items_without_itype->count ) {
166
                new_section("Items do not have itype defined");
187
            new_section("Items do not have itype defined");
167
                while ( my $item = $items_without_itype->next ) {
188
            while ( my $item = $items_without_itype->next ) {
168
                    if (defined $item->biblioitem->itemtype && $item->biblioitem->itemtype ne '' ) {
189
                if ( defined $item->biblioitem->itemtype && $item->biblioitem->itemtype ne '' ) {
169
                        new_item(
190
                    new_item(
170
                        sprintf "Item with itemnumber=%s and biblionumber = %s does not have a itype value, biblio's item type will be used (%s)",
191
                        sprintf
192
                            "Item with itemnumber=%s and biblionumber = %s does not have a itype value, biblio's item type will be used (%s)",
171
                        $item->itemnumber, $item->biblioitem->biblionumber, $item->biblioitem->itemtype
193
                        $item->itemnumber, $item->biblioitem->biblionumber, $item->biblioitem->itemtype
172
                        );
194
                    );
173
                        } else {
195
                } else {
174
                        new_item(
196
                    new_item(
175
                        sprintf "Item with itemnumber=%s and biblionumber = %s does not have a itype value, additionally no item type defined for biblionumber=%s",
197
                        sprintf
198
                            "Item with itemnumber=%s and biblionumber = %s does not have a itype value, additionally no item type defined for biblionumber=%s",
176
                        $item->itemnumber, $item->biblioitem->biblionumber, $item->biblioitem->biblionumber
199
                        $item->itemnumber, $item->biblioitem->biblionumber, $item->biblioitem->biblionumber
177
                        );
200
                    );
178
                    }
179
                }
201
                }
180
                new_hint("The system preference item-level_itypes expects item types to be defined at item level");
181
            }
202
            }
182
        }else{
203
            new_hint("The system preference item-level_itypes expects item types to be defined at item level");
183
            my $biblioitems_without_itemtype = Koha::Biblioitems->search( { itemtype => undef } );
204
        }
184
            if ( $biblioitems_without_itemtype->count ) {
205
    } else {
185
                new_section("Biblioitems do not have itemtype defined");
206
        my $biblioitems_without_itemtype = Koha::Biblioitems->search( { itemtype => undef } );
186
                while ( my $biblioitem = $biblioitems_without_itemtype->next ) {
207
        if ( $biblioitems_without_itemtype->count ) {
187
                    new_item(
208
            new_section("Biblioitems do not have itemtype defined");
209
            while ( my $biblioitem = $biblioitems_without_itemtype->next ) {
210
                new_item(
188
                    sprintf "Biblioitem with biblioitemnumber=%s does not have a itemtype value",
211
                    sprintf "Biblioitem with biblioitemnumber=%s does not have a itemtype value",
189
                    $biblioitem->biblioitemnumber
212
                    $biblioitem->biblioitemnumber
190
                    );
213
                );
191
                }
192
                new_hint("The system preference item-level_itypes expects item types to be defined at biblio level");
193
            }
214
            }
215
            new_hint("The system preference item-level_itypes expects item types to be defined at biblio level");
194
        }
216
        }
217
    }
195
218
196
        my @itemtypes = Koha::ItemTypes->search->get_column('itemtype');
219
    my @itemtypes = Koha::ItemTypes->search->get_column('itemtype');
197
        if ( C4::Context->preference('item-level_itypes') ) {
220
    if ( C4::Context->preference('item-level_itypes') ) {
198
            my $items_with_invalid_itype = Koha::Items->search( { -and => [itype => { not_in => \@itemtypes }, itype => { '!=' => '' }] } );
221
        my $items_with_invalid_itype =
199
            if ( $items_with_invalid_itype->count ) {
222
            Koha::Items->search( { -and => [ itype => { not_in => \@itemtypes }, itype => { '!=' => '' } ] } );
200
                new_section("Items have invalid itype defined");
223
        if ( $items_with_invalid_itype->count ) {
201
                while ( my $item = $items_with_invalid_itype->next ) {
224
            new_section("Items have invalid itype defined");
202
                    new_item(
225
            while ( my $item = $items_with_invalid_itype->next ) {
226
                new_item(
203
                    sprintf "Item with itemnumber=%s, biblionumber=%s does not have a valid itype value (%s)",
227
                    sprintf "Item with itemnumber=%s, biblionumber=%s does not have a valid itype value (%s)",
204
                    $item->itemnumber, $item->biblionumber, $item->itype
228
                    $item->itemnumber, $item->biblionumber, $item->itype
205
                    );
229
                );
206
                }
207
                new_hint("The items must have a itype value that is defined in the item types of Koha (Home › Administration › Item types administration)");
208
            }
230
            }
209
        }else{
231
            new_hint(
210
            my $biblioitems_with_invalid_itemtype = Koha::Biblioitems->search(
232
                "The items must have a itype value that is defined in the item types of Koha (Home › Administration › Item types administration)"
211
            { itemtype => { not_in => \@itemtypes } }
212
            );
233
            );
213
            if ( $biblioitems_with_invalid_itemtype->count ) {
234
        }
214
                new_section("Biblioitems do not have itemtype defined");
235
    } else {
215
                while ( my $biblioitem = $biblioitems_with_invalid_itemtype->next ) {
236
        my $biblioitems_with_invalid_itemtype = Koha::Biblioitems->search( { itemtype => { not_in => \@itemtypes } } );
216
                    new_item(
237
        if ( $biblioitems_with_invalid_itemtype->count ) {
238
            new_section("Biblioitems do not have itemtype defined");
239
            while ( my $biblioitem = $biblioitems_with_invalid_itemtype->next ) {
240
                new_item(
217
                    sprintf "Biblioitem with biblioitemnumber=%s does not have a valid itemtype value",
241
                    sprintf "Biblioitem with biblioitemnumber=%s does not have a valid itemtype value",
218
                    $biblioitem->biblioitemnumber
242
                    $biblioitem->biblioitemnumber
219
                    );
243
                );
220
                }
221
                new_hint("The biblioitems must have a itemtype value that is defined in the item types of Koha (Home › Administration › Item types administration)");
222
            }
244
            }
245
            new_hint(
246
                "The biblioitems must have a itemtype value that is defined in the item types of Koha (Home › Administration › Item types administration)"
247
            );
223
        }
248
        }
249
    }
224
250
225
        my ( @decoding_errors, @ids_not_in_marc );
251
    my ( @decoding_errors, @ids_not_in_marc );
226
        my $biblios = Koha::Biblios->search;
252
    my $biblios = Koha::Biblios->search;
227
        my ( $biblio_tag,     $biblio_subfield )     = C4::Biblio::GetMarcFromKohaField( "biblio.biblionumber" );
253
    my ( $biblio_tag,     $biblio_subfield )     = C4::Biblio::GetMarcFromKohaField("biblio.biblionumber");
228
        my ( $biblioitem_tag, $biblioitem_subfield ) = C4::Biblio::GetMarcFromKohaField( "biblioitems.biblioitemnumber" );
254
    my ( $biblioitem_tag, $biblioitem_subfield ) = C4::Biblio::GetMarcFromKohaField("biblioitems.biblioitemnumber");
229
        while ( my $biblio = $biblios->next ) {
255
    while ( my $biblio = $biblios->next ) {
230
            my $record = eval{$biblio->metadata->record;};
256
        my $record = eval { $biblio->metadata->record; };
231
            if ($@) {
257
        if ($@) {
232
                push @decoding_errors, $@;
258
            push @decoding_errors, $@;
233
                next;
259
            next;
234
            }
260
        }
235
            my ( $biblionumber, $biblioitemnumber );
261
        my ( $biblionumber, $biblioitemnumber );
236
            if ( $biblio_tag < 10 ) {
262
        if ( $biblio_tag < 10 ) {
237
                my $biblio_control_field = $record->field($biblio_tag);
263
            my $biblio_control_field = $record->field($biblio_tag);
238
                $biblionumber = $biblio_control_field->data if $biblio_control_field;
264
            $biblionumber = $biblio_control_field->data if $biblio_control_field;
239
                } else {
265
        } else {
240
                $biblionumber = $record->subfield( $biblio_tag, $biblio_subfield );
266
            $biblionumber = $record->subfield( $biblio_tag, $biblio_subfield );
241
            }
267
        }
242
            if ( $biblioitem_tag < 10 ) {
268
        if ( $biblioitem_tag < 10 ) {
243
                my $biblioitem_control_field = $record->field($biblioitem_tag);
269
            my $biblioitem_control_field = $record->field($biblioitem_tag);
244
                $biblioitemnumber = $biblioitem_control_field->data if $biblioitem_control_field;
270
            $biblioitemnumber = $biblioitem_control_field->data if $biblioitem_control_field;
245
                } else {
271
        } else {
246
                $biblioitemnumber = $record->subfield( $biblioitem_tag, $biblioitem_subfield );
272
            $biblioitemnumber = $record->subfield( $biblioitem_tag, $biblioitem_subfield );
247
            }
273
        }
248
            if ( $biblionumber != $biblio->biblionumber ) {
274
        if ( $biblionumber != $biblio->biblionumber ) {
249
                push @ids_not_in_marc,
275
            push @ids_not_in_marc,
250
                {
276
                {
251
                biblionumber         => $biblio->biblionumber,
277
                biblionumber         => $biblio->biblionumber,
252
                biblionumber_in_marc => $biblionumber,
278
                biblionumber_in_marc => $biblionumber,
253
                };
279
                };
254
            }
280
        }
255
            if ( $biblioitemnumber != $biblio->biblioitem->biblioitemnumber ) {
281
        if ( $biblioitemnumber != $biblio->biblioitem->biblioitemnumber ) {
256
                push @ids_not_in_marc,
282
            push @ids_not_in_marc,
257
                {
283
                {
258
                biblionumber     => $biblio->biblionumber,
284
                biblionumber             => $biblio->biblionumber,
259
                biblioitemnumber => $biblio->biblioitem->biblioitemnumber,
285
                biblioitemnumber         => $biblio->biblioitem->biblioitemnumber,
260
                biblioitemnumber_in_marc => $biblionumber,
286
                biblioitemnumber_in_marc => $biblionumber,
261
                };
287
                };
262
            }
263
        }
264
        if ( @decoding_errors ) {
265
            new_section("Bibliographic records have invalid MARCXML");
266
            new_item($_) for @decoding_errors;
267
            new_hint("The bibliographic records must have a valid MARCXML or you will face encoding issues or wrong displays");
268
        }
288
        }
269
        if (@ids_not_in_marc) {
289
    }
270
            new_section("Bibliographic records have MARCXML without biblionumber or biblioitemnumber");
290
    if (@decoding_errors) {
271
            for my $id (@ids_not_in_marc) {
291
        new_section("Bibliographic records have invalid MARCXML");
272
                if ( exists $id->{biblioitemnumber} ) {
292
        new_item($_) for @decoding_errors;
273
                    new_item(
293
        new_hint(
274
                    sprintf(q{Biblionumber %s has biblioitemnumber '%s' but should be '%s' in %s$%s},
294
            "The bibliographic records must have a valid MARCXML or you will face encoding issues or wrong displays");
275
                    $id->{biblionumber},
295
    }
276
                    $id->{biblioitemnumber},
296
    if (@ids_not_in_marc) {
277
                    $id->{biblioitemnumber_in_marc},
297
        new_section("Bibliographic records have MARCXML without biblionumber or biblioitemnumber");
278
                    $biblioitem_tag,
298
        for my $id (@ids_not_in_marc) {
279
                    $biblioitem_subfield,
299
            if ( exists $id->{biblioitemnumber} ) {
300
                new_item(
301
                    sprintf(
302
                        q{Biblionumber %s has biblioitemnumber '%s' but should be '%s' in %s$%s},
303
                        $id->{biblionumber},
304
                        $id->{biblioitemnumber},
305
                        $id->{biblioitemnumber_in_marc},
306
                        $biblioitem_tag,
307
                        $biblioitem_subfield,
280
                    )
308
                    )
281
                    );
309
                );
282
                }else{
310
            } else {
283
                    new_item(
311
                new_item(
284
                    sprintf(q{Biblionumber %s has '%s' in %s$%s},
312
                    sprintf(
285
                    $id->{biblionumber},
313
                        q{Biblionumber %s has '%s' in %s$%s},
286
                    $id->{biblionumber_in_marc},
314
                        $id->{biblionumber},
287
                    $biblio_tag,
315
                        $id->{biblionumber_in_marc},
288
                    $biblio_subfield,
316
                        $biblio_tag,
317
                        $biblio_subfield,
289
                    )
318
                    )
290
                    );
319
                );
291
                }
292
            }
320
            }
293
            new_hint("The bibliographic records must have the biblionumber and biblioitemnumber in MARCXML");
294
        }
321
        }
322
        new_hint("The bibliographic records must have the biblionumber and biblioitemnumber in MARCXML");
295
    }
323
    }
324
}
296
325
297
    sub CheckItemsFramework {
326
sub CheckItemsFramework {
298
        my @framework_codes = Koha::BiblioFrameworks->search()->get_column('frameworkcode');
327
    my @framework_codes = Koha::BiblioFrameworks->search()->get_column('frameworkcode');
299
        push @framework_codes,""; # The default is not stored in frameworks, we need to force it
328
    push @framework_codes, "";    # The default is not stored in frameworks, we need to force it
300
329
301
        my $invalid_av_per_framework = {};
330
    my $invalid_av_per_framework = {};
302
        foreach my $frameworkcode ( @framework_codes ) {
331
    foreach my $frameworkcode (@framework_codes) {
303
            # We are only checking fields that are mapped to DB fields
332
304
            my $msss = Koha::MarcSubfieldStructures->search({
333
        # We are only checking fields that are mapped to DB fields
305
            frameworkcode => $frameworkcode,
334
        my $msss = Koha::MarcSubfieldStructures->search(
306
            authorised_value => {
335
            {
307
            '!=' => [ -and => ( undef, '' ) ]
336
                frameworkcode    => $frameworkcode,
308
            },
337
                authorised_value => { '!=' => [ -and => ( undef, '' ) ] },
309
            kohafield => {
338
                kohafield        => { '!=' => [ -and => ( undef, '' ) ] }
310
            '!=' => [ -and => ( undef, '' ) ]
339
            }
311
        }
340
        );
312
        });
313
        while ( my $mss = $msss->next ) {
341
        while ( my $mss = $msss->next ) {
314
            my $kohafield = $mss->kohafield;
342
            my $kohafield = $mss->kohafield;
315
            my $av = $mss->authorised_value;
343
            my $av        = $mss->authorised_value;
316
            next if grep {$_ eq $av} qw( branches itemtypes cn_source ); # internal categories
344
            next if grep { $_ eq $av } qw( branches itemtypes cn_source );    # internal categories
317
345
318
            my $avs = Koha::AuthorisedValues->search_by_koha_field(
346
            my $avs = Koha::AuthorisedValues->search_by_koha_field(
319
            {
347
                {
320
            frameworkcode => $frameworkcode,
348
                    frameworkcode => $frameworkcode,
321
            kohafield     => $kohafield,
349
                    kohafield     => $kohafield,
322
        }
350
                }
323
        );
351
            );
324
        my $tmp_kohafield = $kohafield;
352
            my $tmp_kohafield = $kohafield;
325
        if ( $tmp_kohafield =~ /^biblioitems/ ) {
353
            if ( $tmp_kohafield =~ /^biblioitems/ ) {
326
            $tmp_kohafield =~ s|biblioitems|biblioitem|;
354
                $tmp_kohafield =~ s|biblioitems|biblioitem|;
327
            } else {
355
            } else {
328
            $tmp_kohafield =~ s|items|me|;
356
                $tmp_kohafield =~ s|items|me|;
329
        }
357
            }
330
        # replace items.attr with me.attr
331
358
332
        # We are only checking biblios with items
359
            # replace items.attr with me.attr
333
        my $items = Koha::Items->search(
360
334
        {
361
            # We are only checking biblios with items
335
        $tmp_kohafield =>
362
            my $items = Koha::Items->search(
336
        {
363
                {
337
        -not_in => [ $avs->get_column('authorised_value'), '' ],
364
                    $tmp_kohafield => {
338
        '!='    => undef,
365
                        -not_in => [ $avs->get_column('authorised_value'), '' ],
339
        },
366
                        '!='    => undef,
340
        'biblio.frameworkcode' => $frameworkcode
367
                    },
341
        },
368
                    'biblio.frameworkcode' => $frameworkcode
342
        { join => [ 'biblioitem', 'biblio' ] }
369
                },
343
        );
370
                { join => [ 'biblioitem', 'biblio' ] }
344
        if ( $items->count ) {
371
            );
345
            $invalid_av_per_framework->{ $frameworkcode }->{$av} =
372
            if ( $items->count ) {
346
            { items => $items, kohafield => $kohafield };
373
                $invalid_av_per_framework->{$frameworkcode}->{$av} =
374
                    { items => $items, kohafield => $kohafield };
375
            }
347
        }
376
        }
348
    }
377
    }
349
}
378
    if (%$invalid_av_per_framework) {
350
if (%$invalid_av_per_framework) {
379
        new_section('Wrong values linked to authorised values');
351
    new_section('Wrong values linked to authorised values');
380
        for my $frameworkcode ( keys %$invalid_av_per_framework ) {
352
    for my $frameworkcode ( keys %$invalid_av_per_framework ) {
381
            while ( my ( $av_category, $v ) = each %{ $invalid_av_per_framework->{$frameworkcode} } ) {
353
        while ( my ( $av_category, $v ) = each %{$invalid_av_per_framework->{$frameworkcode}} ) {
382
                my $items     = $v->{items};
354
            my $items     = $v->{items};
383
                my $kohafield = $v->{kohafield};
355
            my $kohafield = $v->{kohafield};
384
                my ( $table, $column ) = split '\.', $kohafield;
356
            my ( $table, $column ) = split '\.', $kohafield;
385
                my $output;
357
            my $output;
386
                while ( my $i = $items->next ) {
358
            while ( my $i = $items->next ) {
387
                    my $value =
359
                my $value = $table eq 'items'
388
                          $table eq 'items'  ? $i->$column
360
                ? $i->$column
389
                        : $table eq 'biblio' ? $i->biblio->$column
361
                : $table eq 'biblio'
390
                        :                      $i->biblioitem->$column;
362
                ? $i->biblio->$column
391
                    $output .= " {" . $i->itemnumber . " and " . $i->biblioitem->biblionumber . " => " . $value . "}\n";
363
                : $i->biblioitem->$column;
392
                }
364
                $output .= " {" . $i->itemnumber . " and " . $i->biblioitem->biblionumber. " => " . $value . "}\n";
393
                new_item(
394
                    sprintf(
395
                              "The Framework *%s* is using the authorised value's category *%s*, "
396
                            . "but the following %s do not have a value defined ({itemnumber and biblionumber => value }):\n%s",
397
                        $frameworkcode, $av_category, $kohafield, $output
398
                    )
399
                );
365
            }
400
            }
366
            new_item(
367
            sprintf(
368
            "The Framework *%s* is using the authorised value's category *%s*, "
369
            . "but the following %s do not have a value defined ({itemnumber and biblionumber => value }):\n%s",
370
            $frameworkcode, $av_category, $kohafield, $output
371
            )
372
            );
373
        }
401
        }
374
    }
402
    }
375
}
403
}
376
}
377
404
378
sub CheckItemsTitle {
405
sub CheckItemsTitle {
379
    my $biblios = Koha::Biblios->search({
406
    my $biblios = Koha::Biblios->search(
380
        -or => [
407
        {
381
            title => '',
408
            -or => [
382
            title => undef,
409
                title => '',
383
        ]
410
                title => undef,
384
    });
411
            ]
412
        }
413
    );
385
    if ( $biblios->count ) {
414
    if ( $biblios->count ) {
386
        my ( $title_tag, $title_subtag ) = C4::Biblio::GetMarcFromKohaField( 'biblio.title' );
415
        my ( $title_tag, $title_subtag ) = C4::Biblio::GetMarcFromKohaField('biblio.title');
387
        my $title_field = $title_tag // '';
416
        my $title_field = $title_tag // '';
388
        $title_field .= '$'.$title_subtag if $title_subtag;
417
        $title_field .= '$' . $title_subtag if $title_subtag;
389
        new_section("Biblio without title $title_field");
418
        new_section("Biblio without title $title_field");
390
        while ( my $biblio = $biblios->next ) {
419
        while ( my $biblio = $biblios->next ) {
391
            new_item(sprintf "Biblio with biblionumber=%s does not have title defined", $biblio->biblionumber);
420
            new_item( sprintf "Biblio with biblionumber=%s does not have title defined", $biblio->biblionumber );
392
        }
421
        }
393
        new_hint("Edit these bibliographic records to define a title");
422
        new_hint("Edit these bibliographic records to define a title");
394
    }
423
    }
Lines 400-406 sub CheckAgeForCategory { Link Here
400
            -not => {
429
            -not => {
401
                -or => {
430
                -or => {
402
                    'me.dateofbirth' => undef,
431
                    'me.dateofbirth' => undef,
403
                    -and => {
432
                    -and             => {
404
                        'categorycode.dateofbirthrequired' => undef,
433
                        'categorycode.dateofbirthrequired' => undef,
405
                        'categorycode.upperagelimit'       => undef,
434
                        'categorycode.upperagelimit'       => undef,
406
                    }
435
                    }
Lines 420-427 sub CheckAgeForCategory { Link Here
420
            my $category = $invalid_patron->category;
449
            my $category = $invalid_patron->category;
421
            new_item(
450
            new_item(
422
                sprintf "Patron borrowernumber=%s has an invalid age of %s for their category '%s' (%s to %s)",
451
                sprintf "Patron borrowernumber=%s has an invalid age of %s for their category '%s' (%s to %s)",
423
                $invalid_patron->borrowernumber, $invalid_patron->get_age, $category->categorycode,
452
                $invalid_patron->borrowernumber,       $invalid_patron->get_age, $category->categorycode,
424
                $category->dateofbirthrequired // '0',  $category->upperagelimit // 'unlimited'
453
                $category->dateofbirthrequired // '0', $category->upperagelimit // 'unlimited'
425
            );
454
            );
426
        }
455
        }
427
        new_hint("You may change the patron's category automatically with misc/cronjobs/update_patrons_category.pl");
456
        new_hint("You may change the patron's category automatically with misc/cronjobs/update_patrons_category.pl");
Lines 661-664 Catch data inconsistencies in Koha database: Link Here
661
690
662
Note: If no options are provided, all tests will be run.
691
Note: If no options are provided, all tests will be run.
663
692
664
=cut
693
=cut
665
- 

Return to bug 36027