From a8434f536c9b011048012b19165644d62399d8ee Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 11 Feb 2026 10:52:49 -0500 Subject: [PATCH 01/10] Issue 399: Add new settings to settings editor --- .../administration/settings/index.tt | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/root/dynamic/templates/administration/settings/index.tt b/root/dynamic/templates/administration/settings/index.tt index 1a6c1dde..ba3e7e03 100644 --- a/root/dynamic/templates/administration/settings/index.tt +++ b/root/dynamic/templates/administration/settings/index.tt @@ -1021,6 +1021,75 @@ + +

[% c.loc("Gratis printing") %]

+
+ +
+ +
+ [% c.loc("pages or funds") %] +
+
+ [% c.loc("Default number of gratis pages or funds to give users for free printing.") %] + + +
+ +
+ [% c.loc("pages or funds") %] +
+
+ [% c.loc("Default number of gratis pages or funds to give guests for free printing.") %] + + +
+ +
+ [% c.loc("Method to use for gratis printing.") %] + + +
+ +
+ [% c.loc("Frequency to reset gratis printing to the default value.") %] + [% c.loc("Daily will reset each night, monthly will reset on the first day of the month, and weekly will reset on the day of the week selected in Gratis printing reset day.") %] + +
+ +
+ +
+ [% c.loc("Day of the week to reset gratis printing.") %] +
+ + +
From 584068e6b6234f02e69009a192086b7cda89a50e Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 11 Feb 2026 10:53:29 -0500 Subject: [PATCH 02/10] Issue 399: Add new column gratis_print_balance to users table --- installer/schema.sql | 1 + installer/versions/5/2.x_gratis_print_balance.sql | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 installer/versions/5/2.x_gratis_print_balance.sql diff --git a/installer/schema.sql b/installer/schema.sql index 01c0ce3a..17d19636 100644 --- a/installer/schema.sql +++ b/installer/schema.sql @@ -414,6 +414,7 @@ CREATE TABLE `users` ( `birthdate` date DEFAULT NULL, `created_on` datetime NOT NULL DEFAULT current_timestamp(), `updated_on` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `gratis_print_balance` int(11) NOT NULL DEFAULT 0, -- number of free prints remaining, will either be a number of pages or a number of cents depending on system settings `firstname` varchar(191) DEFAULT '', `lastname` varchar(191) DEFAULT '', `category` varchar(191) DEFAULT '', diff --git a/installer/versions/5/2.x_gratis_print_balance.sql b/installer/versions/5/2.x_gratis_print_balance.sql new file mode 100644 index 00000000..223a09e0 --- /dev/null +++ b/installer/versions/5/2.x_gratis_print_balance.sql @@ -0,0 +1,3 @@ +ALTER TABLE `users` + ADD COLUMN `gratis_print_balance` INT(11) NOT NULL DEFAULT 0 + COMMENT 'Number of free prints remaining; represents pages or cents depending on system settings'; From 7acf76bc2eb09e846f845c7599facd803af0e4f6 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 11 Feb 2026 11:02:56 -0500 Subject: [PATCH 03/10] Issue 399: Update database schema --- installer/data.sql | 21 +++++++++++++++------ installer/schema.sql | 13 +++++++------ lib/Libki/Schema/DB/Result/Job.pm | 8 ++++---- lib/Libki/Schema/DB/Result/LoginSession.pm | 8 ++++---- lib/Libki/Schema/DB/Result/Message.pm | 8 ++++---- lib/Libki/Schema/DB/Result/PrintFile.pm | 8 ++++---- lib/Libki/Schema/DB/Result/PrintJob.pm | 8 ++++---- lib/Libki/Schema/DB/Result/Role.pm | 8 ++++---- lib/Libki/Schema/DB/Result/Setting.pm | 8 ++++---- lib/Libki/Schema/DB/Result/Transaction.pm | 7 +++---- lib/Libki/Schema/DB/Result/User.pm | 14 ++++++++++++-- 11 files changed, 65 insertions(+), 46 deletions(-) diff --git a/installer/data.sql b/installer/data.sql index ed3fa723..0d59dbba 100644 --- a/installer/data.sql +++ b/installer/data.sql @@ -1,8 +1,9 @@ --- MariaDB dump 10.19 Distrib 10.5.19-MariaDB, for debian-linux-gnu (x86_64) +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.5.29-MariaDB, for debian-linux-gnu (x86_64) -- -- Host: libki-mariadb Database: libki -- ------------------------------------------------------ --- Server version 10.3.5-MariaDB-10.3.5+maria~jessie +-- Server version 12.1.2-MariaDB-ubu2404 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -167,8 +168,8 @@ INSERT INTO `settings` VALUES ('','DefaultGuestSessionTimeAllowance','45'); INSERT INTO `settings` VALUES ('','DefaultGuestTimeAllowance','45'); INSERT INTO `settings` VALUES ('','DefaultSessionTimeAllowance','45'); INSERT INTO `settings` VALUES ('','DefaultTimeAllowance','45'); -INSERT INTO `settings` VALUES ('','DisplayReservationStatusWithin','60'); INSERT INTO `settings` VALUES ('','DisplayPublicReservationsPage','enabled'); +INSERT INTO `settings` VALUES ('','DisplayReservationStatusWithin','60'); INSERT INTO `settings` VALUES ('','GuestBatchCount','40'); INSERT INTO `settings` VALUES ('','MinimumReservationMinutes','5'); INSERT INTO `settings` VALUES ('','PostCrashTimeout','5'); @@ -177,9 +178,8 @@ INSERT INTO `settings` VALUES ('','ReservationShowUsername','RSD'); INSERT INTO `settings` VALUES ('','ReservationTimeout','15'); INSERT INTO `settings` VALUES ('','ShowFirstLastNames','1'); INSERT INTO `settings` VALUES ('','ThirdPartyURL',''); -INSERT INTO `settings` VALUES ('','TimeDisplayFormat','24'); INSERT INTO `settings` VALUES ('','UserCategories',''); -INSERT INTO `settings` VALUES ('','Version','5.2.1'); +INSERT INTO `settings` VALUES ('','Version','5.2.x'); /*!40000 ALTER TABLE `settings` ENABLE KEYS */; UNLOCK TABLES; @@ -192,6 +192,15 @@ LOCK TABLES `statistics` WRITE; /*!40000 ALTER TABLE `statistics` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Dumping data for table `transactions` +-- + +LOCK TABLES `transactions` WRITE; +/*!40000 ALTER TABLE `transactions` DISABLE KEYS */; +/*!40000 ALTER TABLE `transactions` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Dumping data for table `user_roles` -- @@ -218,4 +227,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-07-17 7:52:06 +-- Dump completed on 2026-02-11 10:59:54 diff --git a/installer/schema.sql b/installer/schema.sql index 17d19636..bdbd15c8 100644 --- a/installer/schema.sql +++ b/installer/schema.sql @@ -1,8 +1,9 @@ --- MariaDB dump 10.19 Distrib 10.11.13-MariaDB, for debian-linux-gnu (x86_64) +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.5.29-MariaDB, for debian-linux-gnu (x86_64) -- --- Host: localhost Database: libki +-- Host: libki-mariadb Database: libki -- ------------------------------------------------------ --- Server version 11.8.5-MariaDB-ubu2404 +-- Server version 12.1.2-MariaDB-ubu2404 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -374,7 +375,7 @@ CREATE TABLE `transactions` ( KEY `idx_instance_status` (`instance`,`status`), KEY `idx_created_on` (`created_on`), CONSTRAINT `user_transactions_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -414,11 +415,11 @@ CREATE TABLE `users` ( `birthdate` date DEFAULT NULL, `created_on` datetime NOT NULL DEFAULT current_timestamp(), `updated_on` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `gratis_print_balance` int(11) NOT NULL DEFAULT 0, -- number of free prints remaining, will either be a number of pages or a number of cents depending on system settings `firstname` varchar(191) DEFAULT '', `lastname` varchar(191) DEFAULT '', `category` varchar(191) DEFAULT '', `creation_source` varchar(191) DEFAULT NULL, + `gratis_print_balance` int(11) NOT NULL DEFAULT 0 COMMENT 'Number of free prints remaining; represents pages or cents depending on system settings', PRIMARY KEY (`id`), UNIQUE KEY `unique_username` (`instance`,`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; @@ -433,4 +434,4 @@ CREATE TABLE `users` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2025-12-19 13:32:36 +-- Dump completed on 2026-02-11 10:59:54 diff --git a/lib/Libki/Schema/DB/Result/Job.pm b/lib/Libki/Schema/DB/Result/Job.pm index 3d6829b0..1d2670f0 100644 --- a/lib/Libki/Schema/DB/Result/Job.pm +++ b/lib/Libki/Schema/DB/Result/Job.pm @@ -70,7 +70,7 @@ __PACKAGE__->table("jobs"); =head2 data - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 1 =head2 taken @@ -110,7 +110,7 @@ __PACKAGE__->add_columns( "type", { data_type => "varchar", is_nullable => 0, size => 191 }, "data", - { data_type => "longtext", is_nullable => 1 }, + { data_type => "mediumtext", is_nullable => 1 }, "taken", { data_type => "varchar", is_nullable => 1, size => 191 }, "status", @@ -149,8 +149,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("id"); -# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-04-27 09:23:45 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:D2SKTWMAT1jwHSux1UE7qQ +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:slA0TWq4fcyY7kqYTEuk9g __PACKAGE__->load_components('InflateColumn::Serializer'); __PACKAGE__->add_columns( diff --git a/lib/Libki/Schema/DB/Result/LoginSession.pm b/lib/Libki/Schema/DB/Result/LoginSession.pm index 238c7bce..ac5af6c9 100644 --- a/lib/Libki/Schema/DB/Result/LoginSession.pm +++ b/lib/Libki/Schema/DB/Result/LoginSession.pm @@ -57,7 +57,7 @@ __PACKAGE__->table("login_sessions"); =head2 session_data - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 1 =head2 expires @@ -71,7 +71,7 @@ __PACKAGE__->add_columns( "id", { data_type => "char", is_nullable => 0, size => 72 }, "session_data", - { data_type => "longtext", is_nullable => 1 }, + { data_type => "mediumtext", is_nullable => 1 }, "expires", { data_type => "integer", is_nullable => 1 }, ); @@ -89,8 +89,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("id"); -# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-04-27 09:23:45 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:m+OJsvQRg7FrVcbnVJwBxg +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6VF4JGAZI2UkY4knbkR/XQ # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/Message.pm b/lib/Libki/Schema/DB/Result/Message.pm index f68f0169..d8f906c7 100644 --- a/lib/Libki/Schema/DB/Result/Message.pm +++ b/lib/Libki/Schema/DB/Result/Message.pm @@ -70,7 +70,7 @@ __PACKAGE__->table("messages"); =head2 content - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 0 =cut @@ -83,7 +83,7 @@ __PACKAGE__->add_columns( "user_id", { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, "content", - { data_type => "longtext", is_nullable => 0 }, + { data_type => "mediumtext", is_nullable => 0 }, ); =head1 PRIMARY KEY @@ -116,8 +116,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-04-27 09:23:45 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hn49kjZD6Hzpl6FiOXBHww +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CuV5c2ONcc5nZazLSr+QhQ # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/PrintFile.pm b/lib/Libki/Schema/DB/Result/PrintFile.pm index 1e17122c..812f7e69 100644 --- a/lib/Libki/Schema/DB/Result/PrintFile.pm +++ b/lib/Libki/Schema/DB/Result/PrintFile.pm @@ -64,7 +64,7 @@ __PACKAGE__->table("print_files"); =head2 filename - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 0 =head2 content_type @@ -141,7 +141,7 @@ __PACKAGE__->add_columns( "id", { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, "filename", - { data_type => "longtext", is_nullable => 0 }, + { data_type => "mediumtext", is_nullable => 0 }, "content_type", { data_type => "varchar", is_nullable => 1, size => 191 }, "data", @@ -246,8 +246,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07051 @ 2023-07-11 07:35:11 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9IRAjpODFDD7mIKVnM/Jgg +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:kc5pJ/hX1R5YWDHG53PgHQ # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/PrintJob.pm b/lib/Libki/Schema/DB/Result/PrintJob.pm index bfbb10d8..6d8a32a4 100644 --- a/lib/Libki/Schema/DB/Result/PrintJob.pm +++ b/lib/Libki/Schema/DB/Result/PrintJob.pm @@ -81,7 +81,7 @@ __PACKAGE__->table("print_jobs"); =head2 data - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 1 =head2 printer @@ -148,7 +148,7 @@ __PACKAGE__->add_columns( "copies", { data_type => "integer", is_nullable => 1 }, "data", - { data_type => "longtext", is_nullable => 1 }, + { data_type => "mediumtext", is_nullable => 1 }, "printer", { data_type => "varchar", is_nullable => 0, size => 191 }, "user_id", @@ -240,8 +240,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07051 @ 2023-07-11 07:35:11 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:09Hi0qsW0zShp8vcR24gVg +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jlX7n/s5f08LDVSFfpbM/g __PACKAGE__->load_components('InflateColumn::Serializer'); __PACKAGE__->add_columns( diff --git a/lib/Libki/Schema/DB/Result/Role.pm b/lib/Libki/Schema/DB/Result/Role.pm index 77e63b42..6febaa74 100644 --- a/lib/Libki/Schema/DB/Result/Role.pm +++ b/lib/Libki/Schema/DB/Result/Role.pm @@ -57,7 +57,7 @@ __PACKAGE__->table("roles"); =head2 role - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 1 =cut @@ -66,7 +66,7 @@ __PACKAGE__->add_columns( "id", { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, "role", - { data_type => "longtext", is_nullable => 1 }, + { data_type => "mediumtext", is_nullable => 1 }, ); =head1 PRIMARY KEY @@ -109,8 +109,8 @@ Composing rels: L -> user __PACKAGE__->many_to_many("users", "user_roles", "user"); -# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-04-27 09:23:45 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/EScGDz6Ax+fO+asu+G6sw +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:I0G2JZpQIrURRKmeedBoJA # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/Setting.pm b/lib/Libki/Schema/DB/Result/Setting.pm index 2595918c..05811d8c 100644 --- a/lib/Libki/Schema/DB/Result/Setting.pm +++ b/lib/Libki/Schema/DB/Result/Setting.pm @@ -64,7 +64,7 @@ __PACKAGE__->table("settings"); =head2 value - data_type: 'longtext' + data_type: 'mediumtext' is_nullable: 0 =cut @@ -75,7 +75,7 @@ __PACKAGE__->add_columns( "name", { data_type => "varchar", is_nullable => 0, size => 191 }, "value", - { data_type => "longtext", is_nullable => 0 }, + { data_type => "mediumtext", is_nullable => 0 }, ); =head1 PRIMARY KEY @@ -93,8 +93,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("instance", "name"); -# Created by DBIx::Class::Schema::Loader v0.07049 @ 2021-04-27 09:23:45 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EqZtUoS/kZvDJlZBoafaPQ +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:L3jv3QXJPdbcPUJ5AR3QnA # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/Transaction.pm b/lib/Libki/Schema/DB/Result/Transaction.pm index f543fa85..cae346de 100644 --- a/lib/Libki/Schema/DB/Result/Transaction.pm +++ b/lib/Libki/Schema/DB/Result/Transaction.pm @@ -83,7 +83,6 @@ __PACKAGE__->table("transactions"); =head2 amount_cents data_type: 'integer' - extra: {unsigned => 1} is_nullable: 0 =head2 currency @@ -132,7 +131,7 @@ __PACKAGE__->add_columns( "provider_payment_id", { data_type => "varchar", is_nullable => 1, size => 128 }, "amount_cents", - { data_type => "integer", extra => { unsigned => 1 }, is_nullable => 0 }, + { data_type => "integer", is_nullable => 0 }, "currency", { data_type => "char", default_value => "USD", is_nullable => 0, size => 3 }, "status", @@ -206,8 +205,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07053 @ 2025-12-19 15:32:17 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:C5vxDal47UNOSdaRn9nouQ +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:wTt5kG0X0tOz/Mq55tR78w # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/lib/Libki/Schema/DB/Result/User.pm b/lib/Libki/Schema/DB/Result/User.pm index 3aa669ae..d6972231 100644 --- a/lib/Libki/Schema/DB/Result/User.pm +++ b/lib/Libki/Schema/DB/Result/User.pm @@ -152,6 +152,14 @@ __PACKAGE__->table("users"); is_nullable: 1 size: 191 +=head2 gratis_print_balance + + data_type: 'integer' + default_value: 0 + is_nullable: 0 + +Number of free prints remaining; represents pages or cents depending on system settings + =cut __PACKAGE__->add_columns( @@ -211,6 +219,8 @@ __PACKAGE__->add_columns( { data_type => "varchar", default_value => "", is_nullable => 1, size => 191 }, "creation_source", { data_type => "varchar", is_nullable => 1, size => 191 }, + "gratis_print_balance", + { data_type => "integer", default_value => 0, is_nullable => 0 }, ); =head1 PRIMARY KEY @@ -374,8 +384,8 @@ Composing rels: L -> role __PACKAGE__->many_to_many("roles", "user_roles", "role"); -# Created by DBIx::Class::Schema::Loader v0.07053 @ 2025-12-19 15:32:17 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ieWa+l+vWEQ/vWPaNZ37DQ +# Created by DBIx::Class::Schema::Loader v0.07053 @ 2026-02-11 10:59:52 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:tV3lA7kB36cKoCgfsJq4wg __PACKAGE__->add_columns( 'password' => { From 615e88adc60c63e4b168d363767af6ed8d5756d4 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 11 Feb 2026 14:24:34 -0500 Subject: [PATCH 04/10] Issue 399: Implement cronjob --- script/cronjobs/libki_nightly.pl | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/script/cronjobs/libki_nightly.pl b/script/cronjobs/libki_nightly.pl index 3513425a..5ab2e7d4 100755 --- a/script/cronjobs/libki_nightly.pl +++ b/script/cronjobs/libki_nightly.pl @@ -150,6 +150,35 @@ } } +## Reset gratis printing +my $reset_frequency = $c->setting('GratisPrintingResetFrequency'); +my $reset_day = $c->setting('GratisPrintingResetDay'); +if ( $reset_frequency && $reset_day ) { + my $today = DateTime->today( time_zone => $ENV{LIBKI_TZ} ); + + my $do_reset = 0; + if ( $reset_frequency eq 'daily' ) { + $do_reset = 1; + } + elsif ( $reset_frequency eq 'weekly' ) { + if ( $today->day_name eq $reset_day ) { + $do_reset = 1; + } + } + elsif ( $reset_frequency eq 'monthly' ) { + if ( $today->day == 1 ) { + $do_reset = 1; + } + } + + if ( $do_reset ) { + my $gratis_printing_value = $c->setting('GratisPrintingValue') || 0; + my $gratis_printing_value_guest = $c->setting('GratisPrintingValueGuest') || 0; + + $c->model('DB::User')->search( { is_guest => 'No' } )->update( { gratis_print_balance => $gratis_printing_value } ); + } +} + ## Clear out old print jobs and print files my @print_retention_days = $c->model('DB::Setting')->search( { name => 'PrintJobRetentionDays' } ); foreach my $prd (@print_retention_days) { From da443d41b4537174e43628bb45d010767f6792f6 Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Wed, 11 Feb 2026 14:25:09 -0500 Subject: [PATCH 05/10] Issue 399: Set default gratis print balance for new users --- lib/Libki/Utils/User.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Libki/Utils/User.pm b/lib/Libki/Utils/User.pm index 426d6150..66737759 100644 --- a/lib/Libki/Utils/User.pm +++ b/lib/Libki/Utils/User.pm @@ -70,6 +70,7 @@ sub create_or_update_user { is_troublemaker => 'No', created_on => $now, updated_on => $now, + gratis_print_balance => $c->setting('GratisPrintingValue') || 0, } ); @@ -158,6 +159,7 @@ sub create_guest { updated_on => $now, category => $category, creation_source => 'local', + gratis_print_balance => $c->setting('GratisPrintingValueGuest') || 0, } ); From aef58694c4d1bbe69b9848060f1d3a822ef8c3ff Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Fri, 13 Feb 2026 09:22:14 -0500 Subject: [PATCH 06/10] Issue 399: Implement gratis print balance for admin users table and user editor --- lib/Libki/Controller/Administration.pm | 1 + .../Controller/Administration/API/DataTables.pm | 7 ++++--- lib/Libki/Controller/Administration/API/User.pm | 15 +++++++++------ root/dynamic/templates/administration/index.tt | 13 +++++++++++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/Libki/Controller/Administration.pm b/lib/Libki/Controller/Administration.pm index bff52b1c..198142f5 100644 --- a/lib/Libki/Controller/Administration.pm +++ b/lib/Libki/Controller/Administration.pm @@ -51,6 +51,7 @@ sub index : Path : Args(0) { PrinterConfiguration => $c->setting('PrinterConfiguration'), ShowFirstLastNames => $c->setting('ShowFirstLastNames'), UserCategories => $c->setting('UserCategories'), + GratisPrintingValue => $c->setting('GratisPrintingValue'), locations => \@locations, types => \@types, ); diff --git a/lib/Libki/Controller/Administration/API/DataTables.pm b/lib/Libki/Controller/Administration/API/DataTables.pm index df086c85..4b9f2383 100644 --- a/lib/Libki/Controller/Administration/API/DataTables.pm +++ b/lib/Libki/Controller/Administration/API/DataTables.pm @@ -34,7 +34,7 @@ sub users : Local Args(0) { my $params = $c->req->params; # We need to map the table columns to field names for ordering - my @columns = qw/me.username me.lastname me.firstname me.category allotments.minutes session.minutes me.status me.notes me.is_troublemaker client.name session.status me.creation_source/; + my @columns = qw/me.username me.lastname me.firstname me.category allotments.minutes session.minutes me.funds me.gratis_print_balance me.status me.notes me.is_troublemaker client.name session.status me.creation_source/; my $search_term = $params->{"search[value]"}; my $filter; @@ -127,8 +127,9 @@ sub users : Local Args(0) { category => $u->category, client_name => defined( $u->session ) ? $u->session->client->name : undef, creation_source => $u->creation_source, - firstname => $u->firstname, - funds => $u->funds, + firstname => $u->firstname, + funds => $u->funds, + gratis_print_balance => $u->gratis_print_balance, is_troublemaker => $u->is_troublemaker, lastname => $u->lastname, minutes => $u->session ? $u->session->minutes : undef, diff --git a/lib/Libki/Controller/Administration/API/User.pm b/lib/Libki/Controller/Administration/API/User.pm index 85a79a83..12229d0b 100644 --- a/lib/Libki/Controller/Administration/API/User.pm +++ b/lib/Libki/Controller/Administration/API/User.pm @@ -50,8 +50,9 @@ sub get : Local : Args(1) { minutes => $user->minutes($c), status => $user->status, notes => $user->notes, - funds => $user->funds, - is_troublemaker => $user->is_troublemaker, + funds => $user->funds, + gratis_print_balance => $user->gratis_print_balance, + is_troublemaker => $user->is_troublemaker, troublemaker_until => defined( $user->troublemaker_until ) ? $user->troublemaker_until->strftime('%Y-%m-%d 23:59') : undef, @@ -226,8 +227,9 @@ sub update : Local : Args(0) { my $category = $c->request->params->{category}; my $minutes = $c->request->params->{'minutes'}; my $funds = $c->request->params->{'funds'}; - my $notes = $c->request->params->{'notes'}; - my $status = $c->request->params->{'status'}; + my $notes = $c->request->params->{'notes'}; + my $gratis_print_balance = $c->request->params->{'gratis_print_balance'} || 0; + my $status = $c->request->params->{'status'}; my @roles = $c->request->params->{'roles'} || []; # For some reason the list of checkboxes are created @@ -249,8 +251,9 @@ sub update : Local : Args(0) { firstname => $firstname, lastname => $lastname, - category => $category, - notes => $notes, + category => $category, + gratis_print_balance => $gratis_print_balance, + notes => $notes, status => $status, updated_on => $now, } diff --git a/root/dynamic/templates/administration/index.tt b/root/dynamic/templates/administration/index.tt index bb628e72..bbd21272 100644 --- a/root/dynamic/templates/administration/index.tt +++ b/root/dynamic/templates/administration/index.tt @@ -54,6 +54,7 @@ [% c.loc("Daily minutes") %] [% c.loc("Session minutes") %] [% c.loc("Funds") %] + [% c.loc("Gratis print balance") %] [% c.loc("Status") %] [% c.loc("Notes") %] [% c.loc("Troublemaker") %] @@ -570,6 +571,13 @@ [% c.loc("Use period as separator when editing funds.") %] + [% IF GratisPrintingValue > 0 %] +
+ + +
+ [% END %] +