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

(-)a/misc/maintenance/search_for_data_inconsistencies.pl (-35 / +159 lines)
Lines 36-47 our %options = ( Link Here
36
    'check-framework' => 0,
36
    'check-framework' => 0,
37
    'check-title'     => 0,
37
    'check-title'     => 0,
38
    'check-age'       => 0,
38
    'check-age'       => 0,
39
    'skip-branch'     => 1,
39
    'check-loop'      => 0,
40
    'skip-auth'       => 1,
40
    'skip-branch'     => 0,
41
    'skip-status'     => 1,
41
    'skip-auth'       => 0,
42
    'skip-framework'  => 1,
42
    'skip-status'     => 0,
43
    'skip-title'      => 1,
43
    'skip-framework'  => 0,
44
    'skip-age'        => 1,
44
    'skip-title'      => 0,
45
    'skip-age'        => 0,
46
    'skip-loop'       => 0,
45
    'help'            => 0,
47
    'help'            => 0,
46
);
48
);
47
49
Lines 53-64 GetOptions( Link Here
53
    'check-framework' => sub { $options{'check-framework'} = 1 },
55
    'check-framework' => sub { $options{'check-framework'} = 1 },
54
    'check-title'     => sub { $options{'check-title'}     = 1 },
56
    'check-title'     => sub { $options{'check-title'}     = 1 },
55
    'check-age'       => sub { $options{'check-age'}       = 1 },
57
    'check-age'       => sub { $options{'check-age'}       = 1 },
56
    'skip-branch'     => sub { $options{'skip-branch'}     = 0 },
58
    'check-loop'      => sub { $options{'check-loop'}      = 1 },
57
    'skip-auth'       => sub { $options{'skip-auth'}       = 0 },
59
    'skip-branch'     => sub { $options{'skip-branch'}     = 1 },
58
    'skip-status'     => sub { $options{'skip-status'}     = 0 },
60
    'skip-auth'       => sub { $options{'skip-auth'}       = 1 },
59
    'skip-framework'  => sub { $options{'skip-framework'}  = 0 },
61
    'skip-status'     => sub { $options{'skip-status'}     = 1 },
60
    'skip-title'      => sub { $options{'skip-title'}      = 0 },
62
    'skip-framework'  => sub { $options{'skip-framework'}  = 1 },
61
    'skip-age'        => sub { $options{'skip-age'}        = 0 },
63
    'skip-title'      => sub { $options{'skip-title'}      = 1 },
64
    'skip-age'        => sub { $options{'skip-age'}        = 1 },
65
    'skip-loop'       => sub { $options{'skip-loop'}       = 1 },
62
    'help'            => sub { $options{'help'}            = 1; },
66
    'help'            => sub { $options{'help'}            = 1; },
63
) or pod2usage(2);    # Print usage if invalid options are provided
67
) or pod2usage(2);    # Print usage if invalid options are provided
64
68
Lines 74-87 GetOptions( Link Here
74
# Print usage and exit if --help flag is provided
78
# Print usage and exit if --help flag is provided
75
pod2usage(1) if $options{'help'};
79
pod2usage(1) if $options{'help'};
76
80
77
# Run tests based on options
81
# Set skip options based on check options
78
set_skip_options();
82
set_skip_options();
79
CheckItemsBranch()     if $options{'check-branch'}    || $options{'skip-branch'};
83
# Set all check options to 1 if none are provided, unless specified skip options
80
CheckItemsAuthHeader() if $options{'check-auth'}      || $options{'skip-auth'};
84
set_all_check_options_if_none_provided();
81
CheckItemsStatus()     if $options{'check-status'}    || $options{'skip-status'};
85
# Run checks based on options
82
CheckItemsFramework()  if $options{'check-framework'} || $options{'skip-framework'};
86
CheckItemsBranch()       if $options{'check-branch'}    && !$options{'skip-branch'};
83
CheckItemsTitle()      if $options{'check-title'}     || $options{'skip-title'};
87
CheckItemsAuthHeader()   if $options{'check-auth'}      && !$options{'skip-auth'};
84
CheckAgeForCategory()  if $options{'check-age'}       || $options{'skip-age'};
88
CheckItemsStatus()       if $options{'check-status'}    && !$options{'skip-status'};
89
CheckItemsFramework()    if $options{'check-framework'} && !$options{'skip-framework'};
90
CheckItemsTitle()        if $options{'check-title'}     && !$options{'skip-title'};
91
CheckAgeForCategory()    if $options{'check-age'}       && !$options{'skip-age'};
92
CheckRelationshipsLoop() if $options{'check-loop'}      && !$options{'skip-loop'};
85
93
86
# Handle invalid options
94
# Handle invalid options
87
sub handle_invalid_options {
95
sub handle_invalid_options {
Lines 92-106 sub handle_invalid_options { Link Here
92
100
93
# Set skip options based on check options
101
# Set skip options based on check options
94
sub set_skip_options {
102
sub set_skip_options {
95
    my $has_check_option = grep { $options{$_} == 1 } grep { /^check-/ } keys %options;
103
    # 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;
96
    if ($has_check_option) {
105
    if ($has_check_option) {
106
        # if a least one skip option is provided, print a warning
107
        my $has_skip_option = grep { $options{$_} == 1 } grep { /^skip-/ } keys %options;
108
        if ($has_skip_option) {
109
            print("Warning : skip options are ignored when check options are provided\n")
110
        }
111
        # Set all skip options to 0
97
        foreach my $key (keys %options) {
112
        foreach my $key (keys %options) {
98
            $options{$key} = 0 if $key =~ /^skip-/;
113
            if ($key =~ /^skip-/) {
114
                $options{$key} = 0;
115
            }
99
        }
116
        }
100
    }
117
    }
101
    return %options;
118
    return %options;
102
}
119
}
103
120
121
# Set all check options to 1 if none are provided, considering skip options
122
sub set_all_check_options_if_none_provided {
123
    my $any_check_option_provided = grep { $options{$_} } grep { /^check-/ } keys %options;
124
    if (!$any_check_option_provided) {
125
        foreach my $key (keys %options) {
126
            if ($key =~ /^check-/) {
127
                my $skip_key = $key;
128
                $skip_key =~ s/^check-/skip-/;
129
                # Set check option to 1 unless the corresponding skip option indicated
130
                $options{$key} = 1 unless $options{$skip_key};
131
            }
132
        }
133
    }
134
}
135
104
sub CheckItemsBranch {
136
sub CheckItemsBranch {
105
    my $items = Koha::Items->search({ -or => { homebranch => undef, holdingbranch => undef }});
137
    my $items = Koha::Items->search({ -or => { homebranch => undef, holdingbranch => undef }});
106
    if ( $items->count ) { new_section("Not defined items.homebranch and/or items.holdingbranch")}
138
    if ( $items->count ) { new_section("Not defined items.homebranch and/or items.holdingbranch")}
Lines 396-401 sub CheckAgeForCategory { Link Here
396
    }
428
    }
397
}
429
}
398
430
431
sub CheckRelationshipsLoop {
432
    my @loop_borrowers_relationships;
433
    my @guarantor_ids = Koha::Patron::Relationships->_resultset->get_column('guarantor_id')->all();
434
    my @guarantee_ids = Koha::Patron::Relationships->_resultset->get_column('guarantee_id')->all();
435
436
    foreach my $guarantor_id (@guarantor_ids) {
437
        foreach my $guarantee_id (@guarantee_ids) {
438
            if ( $guarantor_id == $guarantee_id ) {
439
440
                my $relation_guarantor_id;
441
                my $relation_guarantee_id;
442
                my $size_list;
443
                my $tmp_garantor_id = $guarantor_id;
444
                my @guarantor_ids;
445
446
                do {
447
                    my @relationship_for_go = Koha::Patron::Relationships->search(
448
                        {
449
                            -or => [
450
                                'guarantor_id' => { '=', $tmp_garantor_id },
451
                            ]
452
                        },
453
                    )->as_list;
454
                    $size_list = scalar @relationship_for_go;
455
456
                    foreach my $relation (@relationship_for_go) {
457
                        $relation_guarantor_id = $relation->guarantor_id;
458
                        unless ( grep { $_ == $relation_guarantor_id } @guarantor_ids ) {
459
                            push @guarantor_ids, $relation_guarantor_id;
460
                        }
461
                        $relation_guarantee_id = $relation->guarantee_id;
462
463
                        my @relationship_for_go = Koha::Patron::Relationships->search(
464
                            {
465
                                -or => [
466
                                    'guarantor_id' => { '=', $relation_guarantee_id },
467
                                ]
468
                            },
469
                        )->as_list;
470
                        $size_list = scalar @relationship_for_go;
471
472
                        if ( $guarantor_id == $relation_guarantee_id ) {
473
                            last;
474
                        }
475
476
                        foreach my $relation (@relationship_for_go) {
477
                            $relation_guarantor_id = $relation->guarantor_id;
478
                            unless ( grep { $_ == $relation_guarantor_id } @guarantor_ids ) {
479
                                push @guarantor_ids, $relation_guarantor_id;
480
                            }
481
                            $relation_guarantee_id = $relation->guarantee_id;
482
483
                            if ( $guarantor_id == $relation_guarantee_id ) {
484
                                last;
485
                            }
486
                        }
487
                        if ( $guarantor_id == $relation_guarantee_id ) {
488
                            last;
489
                        }
490
                    }
491
492
                    $tmp_garantor_id = $relation_guarantee_id;
493
                } while ( $guarantor_id != $relation_guarantee_id && $size_list > 0 );
494
495
                if ( $guarantor_id == $relation_guarantee_id ) {
496
                    unless ( grep { join( "", sort @$_ ) eq join( "", sort @guarantor_ids ) }
497
                        @loop_borrowers_relationships )
498
                    {
499
                        push @loop_borrowers_relationships, \@guarantor_ids;
500
                    }
501
                }
502
            }
503
        }
504
    }
505
506
    if ( scalar @loop_borrowers_relationships > 0 ) {
507
        new_section("The list of guarantors who are also guarantee.");
508
        my $count = 0;
509
        foreach my $table (@loop_borrowers_relationships) {
510
            $count++;
511
            print "Loop $count, borrowers id  : ";
512
            foreach my $borrower_id (@$table) {
513
                print "$borrower_id , ";
514
            }
515
            print "\n";
516
        }
517
        new_hint("Relationships that form guarantor loops must be deleted");
518
    }
519
}
520
399
sub new_section {
521
sub new_section {
400
    my ( $name ) = @_;
522
    my ( $name ) = @_;
401
    say "\n== $name ==";
523
    say "\n== $name ==";
Lines 427-448 Catch data inconsistencies in Koha database: Link Here
427
    * Bibliographic records without a title
549
    * Bibliographic records without a title
428
    * Invalid MARCXML in bibliographic records
550
    * Invalid MARCXML in bibliographic records
429
    * Patrons with invalid category types due to lower and upper age limits
551
    * Patrons with invalid category types due to lower and upper age limits
552
    * Relationships that form guarantor loops
430
553
431
=head2 OPTIONS
554
=head2 OPTIONS
432
555
433
  --check-branch      Check for items without home or holding library
556
  --check-branch     Check for items without home or holding library
434
  --check-auth        Check for authority records with invalid authority type
557
  --check-auth       Check for authority records with invalid authority type
435
  --check-status      Check for bibliographic records and items without an item type or with an invalid item type
558
  --check-status     Check for bibliographic records and items without an item type or with an invalid item type
436
  --check-framework   Check for invalid values in fields where the framework limits to an authorized value category
559
  --check-framework  Check for invalid values in fields where the framework limits to an authorized value category
437
  --check-title       Check for bibliographic records without a title
560
  --check-title      Check for bibliographic records without a title
438
  --check-age         Check for patrons with invalid age for category
561
  --check-age        Check for patrons with invalid age for category
439
  --skip-branch       Skip checking for items without home or holding library
562
  --check-loop       Check for relationships that form guarantor loops
440
  --skip-auth         Skip checking for authority records with invalid authority type
563
  --skip-branch      Skip checking for items without home or holding library
441
  --skip-status       Skip checking for bibliographic records and items without an item type or with an invalid item type
564
  --skip-auth        Skip checking for authority records with invalid authority type
442
  --skip-framework    Skip checking for invalid values in fields where the framework limits to an authorized value category
565
  --skip-status      Skip checking for bibliographic records and items without an item type or with an invalid item type
443
  --skip-title        Skip checking for bibliographic records without a title
566
  --skip-framework   Skip checking for invalid values in fields where the framework limits to an authorized value category
444
  --skip-age          Skip checking for patrons with invalid age for category
567
  --skip-title       Skip checking for bibliographic records without a title
445
  --help              Print usage information
568
  --skip-age         Skip checking for patrons with invalid age for category
569
  --skip-loop        Skip checking for relationships that form guarantor loops
570
  --help             Print usage information
446
571
447
Note: If no options are provided, all tests will be run.
572
Note: If no options are provided, all tests will be run.
448
573
449
- 

Return to bug 36027