3 # Copyright 2009 PTFS, Inc.
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 use constant DEFAULT_ZEBRAQ_PURGEDAYS => 30;
23 use constant DEFAULT_MAIL_PURGEDAYS => 30;
24 use constant DEFAULT_IMPORT_PURGEDAYS => 60;
25 use constant DEFAULT_LOGS_PURGEDAYS => 180;
26 use constant DEFAULT_MESSAGES_PURGEDAYS => 365;
27 use constant DEFAULT_SEARCHHISTORY_PURGEDAYS => 30;
28 use constant DEFAULT_SHARE_INVITATION_EXPIRY_DAYS => 14;
29 use constant DEFAULT_DEBARMENTS_PURGEDAYS => 30;
32 # find Koha's Perl modules
33 # test carefully before changing this
35 eval { require "$FindBin::Bin/../kohalib.pl" };
38 use Koha::Script -cron;
41 use C4::Search::History;
42 use Getopt::Long qw( GetOptions );
43 use C4::Log qw( cronlogaction );
44 use C4::Accounts qw( purge_zero_balance_fees );
45 use Koha::UploadedFiles;
46 use Koha::Old::Biblios;
48 use Koha::Old::Biblioitems;
49 use Koha::Old::Checkouts;
51 use Koha::Old::Patrons;
52 use Koha::Item::Transfers;
53 use Koha::PseudonymizedTransactions;
54 use Koha::Patron::Messages;
58 Usage: $0 [-h|--help] [--confirm] [--sessions] [--sessdays DAYS] [-v|--verbose] [--zebraqueue DAYS] [-m|--mail] [--merged] [--import DAYS] [--logs DAYS] [--searchhistory DAYS] [--restrictions DAYS] [--all-restrictions] [--fees DAYS] [--temp-uploads] [--temp-uploads-days DAYS] [--uploads-missing 0|1 ] [--statistics DAYS] [--deleted-catalog DAYS] [--deleted-patrons DAYS] [--old-issues DAYS] [--old-reserves DAYS] [--transfers DAYS] [--labels DAYS] [--cards DAYS]
60 -h --help prints this help message, and exits, ignoring all
62 --confirm Confirmation flag, the script will be running in dry-run mode is not set.
63 --sessions purge the sessions table. If you use this while users
64 are logged into Koha, they will have to reconnect.
65 --sessdays DAYS purge only sessions older than DAYS days.
66 -v --verbose will cause the script to give you a bit more information
68 --zebraqueue DAYS purge completed zebraqueue entries older than DAYS days.
69 Defaults to 30 days if no days specified.
70 -m --mail DAYS purge items from the mail queue that are older than DAYS days.
71 Defaults to 30 days if no days specified.
72 --merged purged completed entries from need_merge_authorities.
73 --messages DAYS purge entries from messages table older than DAYS days.
74 Defaults to 365 days if no days specified.
75 --import DAYS purge records from import tables older than DAYS days.
76 Defaults to 60 days if no days specified.
77 --z3950 purge records from import tables that are the result
79 --fees DAYS purge entries accountlines older than DAYS days, where
80 amountoutstanding is 0 or NULL.
81 In the case of --fees, DAYS must be greater than
83 --logs DAYS purge entries from action_logs older than DAYS days.
84 Defaults to 180 days if no days specified.
85 --searchhistory DAYS purge entries from search_history older than DAYS days.
86 Defaults to 30 days if no days specified
87 --list-invites DAYS purge (unaccepted) list share invites older than DAYS
88 days. Defaults to 14 days if no days specified.
89 --restrictions DAYS purge patrons restrictions expired since more than DAYS days.
90 Defaults to 30 days if no days specified.
91 --all-restrictions purge all expired patrons restrictions.
92 --del-exp-selfreg Delete expired self registration accounts
93 --del-unv-selfreg DAYS Delete unverified self registrations older than DAYS
94 --unique-holidays DAYS Delete all unique holidays older than DAYS
95 --temp-uploads Delete temporary uploads.
96 --temp-uploads-days DAYS Override the corresponding preference value.
97 --uploads-missing FLAG Delete upload records for missing files when FLAG is true, count them otherwise
98 --oauth-tokens Delete expired OAuth2 tokens
99 --statistics DAYS Purge statistics entries more than DAYS days old.
100 This table is used to build reports, make sure you are aware of the consequences of this before using it!
101 --deleted-catalog DAYS Purge catalog records deleted more then DAYS days ago
102 (from tables deleteditems, deletedbiblioitems, deletedbiblio_metadata and deletedbiblio).
103 --deleted-patrons DAYS Purge patrons deleted more than DAYS days ago.
104 --old-issues DAYS Purge checkouts (old_issues) returned more than DAYS days ago.
105 --old-reserves DAYS Purge reserves (old_reserves) more than DAYS old.
106 --transfers DAYS Purge transfers completed more than DAYS day ago.
107 --pseudo-transactions DAYS Purge the pseudonymized transactions that have been originally created more than DAYS days ago
108 DAYS is optional and can be replaced by:
109 --pseudo-transactions-from YYYY-MM-DD and/or --pseudo-transactions-to YYYY-MM-DD
110 --labels DAYS Purge item label batches last added to more than DAYS days ago.
111 --cards DAY Purge card creator batches last added to more than DAYS days ago.
129 my $pListShareInvites;
132 my $return_claims = C4::Context->preference('CleanUpDatabaseReturnClaims');
136 my $special_holidays_days;
138 my $temp_uploads_days;
147 my ( $pPseudoTransactions, $pPseudoTransactionsFrom, $pPseudoTransactionsTo );
149 my $lock_days = C4::Context->preference('LockExpiredDelay');
155 'confirm' => \$confirm,
156 'sessions' => \$sessions,
157 'sessdays:i' => \$sess_days,
158 'v|verbose' => \$verbose,
159 'm|mail:i' => \$mail,
160 'zebraqueue:i' => \$zebraqueue_days,
161 'merged' => \$purge_merged,
162 'import:i' => \$pImport,
165 'messages:i' => \$pMessages,
166 'fees:i' => \$fees_days,
167 'searchhistory:i' => \$pSearchhistory,
168 'list-invites:i' => \$pListShareInvites,
169 'restrictions:i' => \$pDebarments,
170 'all-restrictions' => \$allDebarments,
171 'del-exp-selfreg' => \$pExpSelfReg,
172 'del-unv-selfreg' => \$pUnvSelfReg,
173 'unique-holidays:i' => \$special_holidays_days,
174 'temp-uploads' => \$temp_uploads,
175 'temp-uploads-days:i' => \$temp_uploads_days,
176 'uploads-missing:i' => \$uploads_missing,
177 'oauth-tokens' => \$oauth_tokens,
178 'statistics:i' => \$pStatistics,
179 'deleted-catalog:i' => \$pDeletedCatalog,
180 'deleted-patrons:i' => \$pDeletedPatrons,
181 'old-issues:i' => \$pOldIssues,
182 'old-reserves:i' => \$pOldReserves,
183 'transfers:i' => \$pTransfers,
184 'pseudo-transactions:i' => \$pPseudoTransactions,
185 'pseudo-transactions-from:s' => \$pPseudoTransactionsFrom,
186 'pseudo-transactions-to:s' => \$pPseudoTransactionsTo,
187 'labels' => \$labels,
192 $sessions = 1 if $sess_days && $sess_days > 0;
193 $pImport = DEFAULT_IMPORT_PURGEDAYS if defined($pImport) && $pImport == 0;
194 $pLogs = DEFAULT_LOGS_PURGEDAYS if defined($pLogs) && $pLogs == 0;
195 $zebraqueue_days = DEFAULT_ZEBRAQ_PURGEDAYS if defined($zebraqueue_days) && $zebraqueue_days == 0;
196 $mail = DEFAULT_MAIL_PURGEDAYS if defined($mail) && $mail == 0;
197 $pSearchhistory = DEFAULT_SEARCHHISTORY_PURGEDAYS if defined($pSearchhistory) && $pSearchhistory == 0;
198 $pListShareInvites = DEFAULT_SHARE_INVITATION_EXPIRY_DAYS if defined($pListShareInvites) && $pListShareInvites == 0;
199 $pDebarments = DEFAULT_DEBARMENTS_PURGEDAYS if defined($pDebarments) && $pDebarments == 0;
200 $pMessages = DEFAULT_MESSAGES_PURGEDAYS if defined($pMessages) && $pMessages == 0;
215 || $pListShareInvites
220 || $special_holidays_days
222 || defined $uploads_missing
230 || defined $pPseudoTransactions
231 || $pPseudoTransactionsFrom
232 || $pPseudoTransactionsTo
234 || defined $lock_days && $lock_days ne q{}
238 print "You did not specify any cleanup work for the script to do.\n\n";
242 if ($pDebarments && $allDebarments) {
243 print "You can not specify both --restrictions and --all-restrictions.\n\n";
247 say "Confirm flag not passed, running in dry-run mode..." unless $confirm;
249 cronlogaction() unless $confirm;
251 my $dbh = C4::Context->dbh();
255 if ( $sessions && !$sess_days ) {
257 say "Session purge triggered.";
258 $sth = $dbh->prepare(q{ SELECT COUNT(*) FROM sessions });
259 $sth->execute() or die $dbh->errstr;
260 my @count_arr = $sth->fetchrow_array;
261 say $confirm ? "$count_arr[0] entries will be deleted." : "$count_arr[0] entries would be deleted.";
264 $sth = $dbh->prepare(q{ TRUNCATE sessions });
265 $sth->execute() or die $dbh->errstr;
268 print "Done with session purge.\n";
271 elsif ( $sessions && $sess_days > 0 ) {
272 print "Session purge triggered with days>$sess_days.\n" if $verbose;
273 RemoveOldSessions() if $confirm;
274 print "Done with session purge with days>$sess_days.\n" if $verbose;
277 if ($zebraqueue_days) {
279 print "Zebraqueue purge triggered for $zebraqueue_days days.\n" if $verbose;
280 $sth = $dbh->prepare(
282 SELECT id,biblio_auth_number,server,time
284 WHERE done=1 AND time < date_sub(curdate(), INTERVAL ? DAY)
287 $sth->execute($zebraqueue_days) or die $dbh->errstr;
288 $sth2 = $dbh->prepare(q{ DELETE FROM zebraqueue WHERE id=? });
289 while ( my $record = $sth->fetchrow_hashref ) {
291 $sth2->execute( $record->{id} ) or die $dbh->errstr;
296 say $confirm ? "$count records were deleted." : "$count records would have been deleted.";
297 say "Done with zebraqueue purge.";
303 print "Mail queue purge triggered for $mail days.\n" if $verbose;
304 $sth = $dbh->prepare(
306 DELETE FROM message_queue
307 WHERE time_queued < date_sub(curdate(), INTERVAL ? DAY)
311 $sth->execute($mail) or die $dbh->errstr;
315 say $confirm ? "$count messages were deleted from the mail queue." : "Message from message_queue would have been deleted";
316 say "Done with message_queue purge.";
321 print "Purging completed entries from need_merge_authorities.\n" if $verbose;
323 $sth = $dbh->prepare(q{ DELETE FROM need_merge_authorities WHERE done=1 });
324 $sth->execute() or die $dbh->errstr;
326 print "Done with purging need_merge_authorities.\n" if $verbose;
330 print "Purging records from import tables.\n" if $verbose;
331 PurgeImportTables() if $confirm;
332 print "Done with purging import tables.\n" if $verbose;
336 print "Purging Z39.50 records from import tables.\n" if $verbose;
337 PurgeZ3950() if $confirm;
338 print "Done with purging Z39.50 records from import tables.\n" if $verbose;
342 print "Purging records from action_logs.\n" if $verbose;
343 $sth = $dbh->prepare(
345 DELETE FROM action_logs
346 WHERE timestamp < date_sub(curdate(), INTERVAL ? DAY)
350 $sth->execute($pLogs) or die $dbh->errstr;
352 print "Done with purging action_logs.\n" if $verbose;
356 print "Purging messages older than $pMessages days.\n" if $verbose;
357 my $messages = Koha::Patron::Messages->filter_by_last_update(
358 { timestamp_column_name => 'message_date', days => $pMessages } );
359 my $count = $messages->count;
360 $messages->delete if $confirm;
363 ? sprintf( "Done with purging %d messages", $count )
364 : sprintf( "%d messages would have been removed", $count );
369 print "Purging records from accountlines.\n" if $verbose;
370 purge_zero_balance_fees( $fees_days ) if $confirm;
371 print "Done purging records from accountlines.\n" if $verbose;
374 if ($pSearchhistory) {
375 print "Purging records older than $pSearchhistory from search_history.\n" if $verbose;
376 C4::Search::History::delete({ interval => $pSearchhistory }) if $confirm;
377 print "Done with purging search_history.\n" if $verbose;
380 if ($pListShareInvites) {
381 print "Purging unaccepted list share invites older than $pListShareInvites days.\n" if $verbose;
382 $sth = $dbh->prepare(
384 DELETE FROM virtualshelfshares
385 WHERE invitekey IS NOT NULL
386 AND (sharedate + INTERVAL ? DAY) < NOW()
390 $sth->execute($pListShareInvites);
392 print "Done with purging unaccepted list share invites.\n" if $verbose;
396 print "Expired patrons restrictions purge triggered for $pDebarments days.\n" if $verbose;
397 my $count = PurgeDebarments($pDebarments, $confirm);
399 say $confirm ? "$count restrictions were deleted." : "$count restrictions would have been deleted";
400 say "Done with restrictions purge.";
405 print "All expired patrons restrictions purge triggered.\n" if $verbose;
406 my $count = PurgeDebarments(0, $confirm);
408 say $confirm ? "$count restrictions were deleted." : "$count restrictions would have been deleted";
409 say "Done with all restrictions purge.";
413 # Lock expired patrons?
414 if( defined $lock_days && $lock_days ne q{} ) {
415 say "Start locking expired patrons" if $verbose;
416 my $expired_patrons = Koha::Patrons->filter_by_expiration_date({ days => $lock_days })->search({ login_attempts => { '!=' => -1 } });
417 my $count = $expired_patrons->count;
418 $expired_patrons->lock({ remove => 1 }) if $confirm;
420 say $confirm ? sprintf("Locked %d patrons", $count) : sprintf("Found %d patrons", $count);
424 # Handle unsubscribe requests from GDPR consent form, depends on UnsubscribeReflectionDelay preference
425 say "Start lock unsubscribed, anonymize and delete" if $verbose;
426 my $unsubscribed_patrons = Koha::Patrons->search_unsubscribed;
427 my $count = $unsubscribed_patrons->count;
428 $unsubscribed_patrons->lock( { expire => 1, remove => 1 } ) if $confirm;
429 say $confirm ? sprintf("Locked %d patrons", $count) : sprintf("%d patrons would have been locked", $count) if $verbose;
431 # Anonymize patron data, depending on PatronAnonymizeDelay
432 my $anonymize_candidates = Koha::Patrons->search_anonymize_candidates( { locked => 1 } );
433 $count = $anonymize_candidates->count;
434 $anonymize_candidates->anonymize if $confirm;
435 say $confirm ? sprintf("Anonymized %d patrons", $count) : sprintf("%d patrons would have been anonymized", $count) if $verbose;
437 # Remove patron data, depending on PatronRemovalDelay (will raise an exception if problem encountered
438 my $anonymized_patrons = Koha::Patrons->search_anonymized;
439 $count = $anonymized_patrons->count;
441 $anonymized_patrons->delete( { move => 1 } );
447 say $confirm ? sprintf("Deleted %d patrons", $count) : sprintf("%d patrons would have been deleted", $count);
450 # FIXME The output for dry-run mode needs to be improved
451 # But non trivial changes to C4::Members need to be done before.
454 DeleteExpiredSelfRegs();
455 } elsif ( $verbose ) {
456 say "self-registered borrowers may be deleted";
461 DeleteUnverifiedSelfRegs( $pUnvSelfReg );
462 } elsif ( $verbose ) {
463 say "unverified self-registrations may be deleted";
467 if ($special_holidays_days) {
469 DeleteSpecialHolidays( abs($special_holidays_days) );
470 } elsif ( $verbose ) {
471 say "self-registered borrowers may be deleted";
475 if( $temp_uploads ) {
476 # Delete temporary uploads, governed by a pref (unless you override)
477 print "Purging temporary uploads.\n" if $verbose;
479 Koha::UploadedFiles->delete_temporary({
480 defined($temp_uploads_days)
481 ? ( override_pref => $temp_uploads_days )
485 print "Done purging temporary uploads.\n" if $verbose;
488 if( defined $uploads_missing ) {
489 print "Looking for missing uploads\n" if $verbose;
491 my $keep = $uploads_missing == 1 ? 0 : 1;
492 my $count = Koha::UploadedFiles->delete_missing({ keep_record => $keep });
494 print "Counted $count missing uploaded files\n";
496 print "Removed $count records for missing uploads\n";
499 # FIXME need to create a filter_by_missing method (then call ->delete) instead of delete_missing
500 say "Dry-run mode cannot guess how many uploads would have been deleted";
505 require Koha::OAuthAccessTokens;
507 my $tokens = Koha::OAuthAccessTokens->search({ expires => { '<=', time } });
508 my $count = $tokens->count;
509 $tokens->delete if $confirm;
512 ? sprintf( "Removed %d expired OAuth2 tokens", $count )
513 : sprintf( "%d expired OAuth tokens would have been removed", $count );
518 print "Purging statistics older than $pStatistics days.\n" if $verbose;
519 my $statistics = Koha::Statistics->filter_by_last_update(
520 { timestamp_column_name => 'datetime', days => $pStatistics } );
521 my $count = $statistics->count;
522 $statistics->delete if $confirm;
525 ? sprintf( "Done with purging %d statistics", $count )
526 : sprintf( "%d statistics would have been removed", $count );
530 if ($return_claims) {
531 print "Purging return claims older than $return_claims days.\n" if $verbose;
532 $sth = $dbh->prepare(
534 DELETE FROM return_claims
535 WHERE resolved_on < DATE_SUB(CURDATE(), INTERVAL ? DAY)
538 $sth->execute($return_claims);
539 print "Done with purging return claims.\n" if $verbose;
542 if ($pDeletedCatalog) {
543 print "Purging deleted catalog older than $pDeletedCatalog days.\n"
545 my $old_items = Koha::Old::Items->filter_by_last_update( { days => $pDeletedCatalog } );
546 my $old_biblioitems = Koha::Old::Biblioitems->filter_by_last_update( { days => $pDeletedCatalog } );
547 my $old_biblios = Koha::Old::Biblios->filter_by_last_update( { days => $pDeletedCatalog } );
548 my ( $c_i, $c_bi, $c_b ) =
549 ( $old_items->count, $old_biblioitems->count, $old_biblios->count );
552 $old_biblioitems->delete;
553 $old_biblios->delete;
558 ? "Done with purging deleted catalog (%d items, %d biblioitems, %d biblios)."
559 : "Deleted catalog would have been removed (%d items, %d biblioitems, %d biblios).",
564 if ($pDeletedPatrons) {
565 print "Purging deleted patrons older than $pDeletedPatrons days.\n" if $verbose;
566 my $old_patrons = Koha::Old::Patrons->filter_by_last_update(
567 { timestamp_column_name => 'updated_on', days => $pDeletedPatrons } );
568 my $count = $old_patrons->count;
569 $old_patrons->delete if $confirm;
572 ? sprintf "Done with purging %d deleted patrons.", $count
573 : sprintf "%d deleted patrons would have been purged.", $count;
578 print "Purging old checkouts older than $pOldIssues days.\n" if $verbose;
579 my $old_checkouts = Koha::Old::Checkouts->filter_by_last_update( { days => $pOldIssues } );
580 my $count = $old_checkouts->count;
581 $old_checkouts->delete if $confirm;
584 ? sprintf "Done with purging %d old checkouts.", $count
585 : sprintf "%d old checkouts would have been purged.", $count;
590 print "Purging old reserves older than $pOldReserves days.\n" if $verbose;
591 my $old_reserves = Koha::Old::Holds->filter_by_last_update( { days => $pOldReserves } );
592 my $count = $old_reserves->count;
593 $old_reserves->delete if $verbose;
596 ? sprintf "Done with purging %d old reserves.", $count
597 : sprintf "%d old reserves would have been purged.", $count;
602 print "Purging arrived item transfers older than $pTransfers days.\n" if $verbose;
603 my $transfers = Koha::Item::Transfers->filter_by_last_update(
605 timestamp_column_name => 'datearrived',
609 my $count = $transfers->count;
610 $transfers->delete if $verbose;
613 ? sprintf "Done with purging %d transfers.", $count
614 : sprintf "%d transfers would have been purged.", $count;
618 if (defined $pPseudoTransactions or $pPseudoTransactionsFrom or $pPseudoTransactionsTo ) {
619 print "Purging pseudonymized transactions\n" if $verbose;
620 my $anonymized_transactions = Koha::PseudonymizedTransactions->filter_by_last_update(
622 timestamp_column_name => 'datetime',
623 ( defined $pPseudoTransactions ? ( days => $pPseudoTransactions ) : () ),
624 ( $pPseudoTransactionsFrom ? ( from => $pPseudoTransactionsFrom ) : () ),
625 ( $pPseudoTransactionsTo ? ( to => $pPseudoTransactionsTo ) : () ),
628 my $count = $anonymized_transactions->count;
629 $anonymized_transactions->delete if $confirm;
632 ? sprintf "Done with purging %d pseudonymized transactions.", $count
633 : sprintf "%d pseudonymized transactions would have been purged.", $count;
638 print "Purging item label batches last added to more than $labels days ago.\n" if $verbose;
639 my $count = PurgeCreatorBatches($labels, 'labels', $confirm);
642 ? sprintf "Done with purging %d item label batches last added to more than %d days ago.\n", $count, $labels
643 : sprintf "%d item label batches would have been purged.", $count;
648 print "Purging card creator batches last added to more than $cards days ago.\n" if $verbose;
649 my $count = PurgeCreatorBatches($labels, 'patroncards', $confirm);
652 ? sprintf "Done with purging %d card creator batches last added to more than %d days ago.\n", $count, $labels
653 : sprintf "%d card creator batches would have been purged.", $count;
659 sub RemoveOldSessions {
660 my ( $id, $a_session, $limit, $lasttime );
661 $limit = time() - 24 * 3600 * $sess_days;
663 $sth = $dbh->prepare(q{ SELECT id, a_session FROM sessions });
664 $sth->execute or die $dbh->errstr;
665 $sth->bind_columns( \$id, \$a_session );
666 $sth2 = $dbh->prepare(q{ DELETE FROM sessions WHERE id=? });
669 while ( $sth->fetch ) {
671 if ( $a_session =~ /lasttime:\s+'?(\d+)/ ) {
674 elsif ( $a_session =~ /(ATIME|CTIME):\s+'?(\d+)/ ) {
677 if ( $lasttime && $lasttime < $limit ) {
678 $sth2->execute($id) or die $dbh->errstr;
683 print "$count sessions were deleted.\n";
687 sub PurgeImportTables {
689 #First purge import_records
690 #Delete cascades to import_biblios, import_items and import_record_matches
691 $sth = $dbh->prepare(
693 DELETE FROM import_records
694 WHERE upload_timestamp < date_sub(curdate(), INTERVAL ? DAY)
697 $sth->execute($pImport) or die $dbh->errstr;
699 # Now purge import_batches
700 # Timestamp cannot be used here without care, because records are added
701 # continuously to batches without updating timestamp (Z39.50 search).
702 # So we only delete older empty batches.
703 # This delete will therefore not have a cascading effect.
704 $sth = $dbh->prepare(
707 FROM import_batches ba
708 LEFT JOIN import_records re ON re.import_batch_id=ba.import_batch_id
709 WHERE re.import_record_id IS NULL AND
710 ba.upload_timestamp < date_sub(curdate(), INTERVAL ? DAY)
713 $sth->execute($pImport) or die $dbh->errstr;
717 $sth = $dbh->prepare(
719 DELETE FROM import_batches
720 WHERE batch_type = 'z3950'
723 $sth->execute() or die $dbh->errstr;
726 sub PurgeDebarments {
727 require Koha::Patron::Debarments;
728 my ( $days, $doit ) = @_;
730 $sth = $dbh->prepare(
732 SELECT borrower_debarment_id
733 FROM borrower_debarments
734 WHERE expiration < date_sub(curdate(), INTERVAL ? DAY)
737 $sth->execute($days) or die $dbh->errstr;
738 while ( my ($borrower_debarment_id) = $sth->fetchrow_array ) {
739 Koha::Patron::Debarments::DelDebarment($borrower_debarment_id) if $doit;
745 sub PurgeCreatorBatches {
746 require C4::Labels::Batch;
747 my ( $days, $creator, $doit ) = @_;
749 $sth = $dbh->prepare(
751 SELECT batch_id, branch_code FROM creator_batches
754 FROM (SELECT batch_id
758 HAVING max(timestamp) <= date_sub(curdate(),interval ? day)) a)
761 $sth->execute( $creator, $days ) or die $dbh->errstr;
762 while ( my ( $batch_id, $branch_code ) = $sth->fetchrow_array ) {
763 C4::Labels::Batch::delete(
764 batch_id => $batch_id,
765 branch_code => $branch_code
772 sub DeleteExpiredSelfRegs {
773 my $cnt= C4::Members::DeleteExpiredOpacRegistrations();
774 print "Removed $cnt expired self-registered borrowers\n" if $verbose;
777 sub DeleteUnverifiedSelfRegs {
778 my $cnt= C4::Members::DeleteUnverifiedOpacRegistrations( $_[0] );
779 print "Removed $cnt unverified self-registrations\n" if $verbose;
782 sub DeleteSpecialHolidays {
785 my $sth = $dbh->prepare(q{
786 DELETE FROM special_holidays
787 WHERE DATE( CONCAT( year, '-', month, '-', day ) ) < DATE_SUB( CAST(NOW() AS DATE), INTERVAL ? DAY );
789 my $count = $sth->execute( $days ) + 0;
790 print "Removed $count unique holidays\n" if $verbose;